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 }

猜你喜欢

转载自www.cnblogs.com/iamqzh233/p/9427149.html