BZOJ1598: [Usaco2008 Mar]牛跑步
估价函数f(x)=g(x)+d(x),意思就是说加上到终点的最短路为估价。
用堆优化的spfa跑一遍就行了
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define M 10010 4 #define LL long long 5 #define inf 1047483647 6 vector<pair<int, int> > T[M]; 7 struct Edge{ 8 int u, v, w, Next; 9 } G[M]; 10 int head[M], tot; 11 int n, m, k; 12 inline void add1(int u, int v, int w) { 13 G[++ tot] = (Edge){u, v, w, head[u]}; 14 head[u] = tot; 15 } 16 inline void add2(int u, int v, int w) { 17 T[u].push_back(make_pair(v, w)); 18 } 19 bool vis[M]; 20 LL d[M]; 21 priority_queue<pair<LL, int> > Q; 22 inline void Dij(int s) { 23 for(int i = 1; i <= n; ++ i) d[i] = inf; 24 d[s] = 0; 25 Q.push(make_pair(0, s)); 26 while(!Q.empty()) { 27 pair<LL, int> u = Q.top(); Q.pop(); 28 int x = u.second; 29 if(vis[x]) continue; 30 vis[x] = 1; 31 for(int i = 0; i < T[x].size(); ++ i) { 32 int v = T[x][i].first, w = T[x][i].second; 33 if(d[v] > d[x] + w) { 34 d[v] = d[x] + w; 35 Q.push(make_pair(-d[v], v)); 36 } 37 } 38 } 39 } 40 LL Ans[M]; 41 int cnt; 42 int main() { 43 scanf("%d%d%d", &n, &m, &k); 44 memset(head, -1, sizeof(head)); 45 for(int i = 1; i <= m; ++ i) { 46 int u, v, w; 47 scanf("%d%d%d", &u, &v, &w); 48 add2(v, u, w); add1(u, v, w); 49 } 50 Dij(1); 51 memset(Ans, -1, sizeof(Ans)); 52 Q.push(make_pair(-d[n], n)); 53 while(!Q.empty()) { 54 pair<LL, int> u = Q.top(); Q.pop(); 55 int x = u.second; 56 if(x == 1) { 57 Ans[++ cnt] = -u.first; 58 if(cnt >= k) break; 59 } 60 for(int i = head[x]; i != -1; i = G[i].Next) { 61 Q.push(make_pair(u.first + d[x] - G[i].w - d[G[i].v], G[i].v)); 62 } 63 } 64 for(int i = 1; i <= k; ++ i) { 65 printf("%lld\n", Ans[i]); 66 } 67 }