kuangbin_ShortPath P (HDU 4725)

时间:2021-03-29 11:02:47

很有挑战的一题 直接暴力建图的话毫无疑问O(n^2)会TLE 每层虚拟一个点又会让没有点的层也能连过去

参考kuangbin菊苣的方法每层用了两个虚拟点 n+i*2-1 是入口 n+i*2 是出口 然后建单向边就可以了

VA了一次 因为MAXN应该比数据量大两倍 不小心忽略了 至于MAXM直接开到了1e7

#include <iostream>
#include <string>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#define INF 0x3F3F3F3F
using namespace std; const int MAXN = 1e6 + ;
const int MAXM = 2e7 + ; typedef pair<int, int> pii;
struct cmp{
bool operator ()(const pii a, const pii b){
return a.first > b.first;
}
}; int size, head[MAXN], point[MAXM], nxt[MAXM], val[MAXM];
int t, n, m, c, dist[MAXN]; void init()
{
size = ;
memset(head, -, sizeof head);
} inline void add(int from, int to, int value)
{
val[size] = value;
point[size] = to;
nxt[size] = head[from];
head[from] = size++;
} void dij(){
priority_queue<pii, vector<pii>, cmp> q;
memset(dist, 0x3f, sizeof dist);
q.push(make_pair(, ));
dist[] = ;
while(!q.empty()){
pii u = q.top();
q.pop();
if(u.first > dist[u.second]) continue;
for(int i = head[u.second]; ~i; i = nxt[i]){
if(dist[point[i]] > dist[u.second] + val[i]){
dist[point[i]] = dist[u.second] + val[i];
q.push(make_pair(dist[point[i]], point[i]));
}
}
}
} int main()
{
scanf("%d", &t);
for(int kase = ; kase <= t; kase++){
init();
scanf("%d%d%d", &n, &m, &c);
for(int i = ; i <= n; i++){
int layer;
scanf("%d", &layer);
add(n + *layer - , i, );
add(i, n + *layer, );
}
for(int i = ; i < n; i++){
add(n + *i, n + *(i+) - , c);
add(n + *(i+), n + *i - , c);
}
int u, v, w;
for(int i = ; i <= m; i++){
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
add(v, u, w);
} dij();
printf("Case #%d: %d\n", kase, dist[n] == INF ? - : dist[n]);
}
return ;
}