牛跑步
Time Limit: 10 Sec Memory Limit: 162 MB
Description
BESSIE准备用从牛棚跑到池塘的方法来锻炼.
但是因为她懒,她只准备沿着下坡的路跑到池塘, 然后走回牛棚.
BESSIE也不想跑得太远,所以她想走最短的路经.
农场上一共有M 条路, 每条路连接两个用1…N标号的地点.
更方便的是,如果X>Y,则地点X的高度大于地点Y的高度.
地点N是BESSIE的牛棚;地点1是池塘.
很快, BESSIE厌倦了一直走同一条路.所以她想走不同的路,更明确地讲,她想找出K条不同的路经.为了避免过度劳累,她想使这K条路经为最短的K条路经.
请帮助BESSIE找出这K条最短路经的长度.
你的程序需要读入农场的地图,一些从X_i到Y_i 的路经和它们的长度(X_i, Y_i, D_i).
第1行: 3个数: N, M, 和K
第 2…M+1行: 第 i+1 行包含3个数 X_i, Y_i, 和 D_i, 表示一条下坡的路.
Output
第1…K行: 第i行包含第i最短路经的长度,或-1如果这样的路经不存在.如果多条路经有同样的长度,请注意将这些长度逐一列出.
5 8 7
5 4 1
5 3 1
5 2 1
5 1 1
4 3 4
3 1 1
3 2 1
2 1 1
Sample Output
1
2
2
3
6
7
-1
HINT
1 <= M <= 10,000, 1 <= N <= 1000, 1 <= K <= 100
Main idea
给定一张图,输出1~k短路的距离。
Solution
既然是求k短路,那我们使用A搜索,先反向建图,记录终点到每一个点的最短路,然后把这个dist当做估价来跑A即可。可以证明:第k次搜到的路即是k短路。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include<iostream> #include<string> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<queue> using namespace std; typedef long long s64;
const int ONE = 2e6+5;
int n,m,k; int S,T; int dist[ONE],vis[ONE],Output[ONE],tou,wei; int next[ONE],first[ONE],go[ONE],w[ONE],tot; int Ans[ONE],num;
struct point { int x,y,z; }a[ONE];
struct power { int x,real,eva; bool operator <(const power &a) const { return a.real + a.eva < real + eva; } };
inline int get() { int res=1,Q=1; char c; while( (c=getchar())<48 || c>57) if(c=='-')Q=-1; if(Q) res=c-48; while((c=getchar())>=48 && c<=57) res=res*10+c-48; return res*Q; }
void Add(int u,int v,int z) { next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; }
void SPFA(int x) { int q[10000001]; memset(dist,63,sizeof(dist)); tou = 0; wei = 1; vis[x] = 1; dist[x] = 0; q[1] = x; while(tou < wei) { int u = q[++tou]; for(int e=first[u];e;e=next[e]) { int v = go[e]; if(dist[v] > dist[u] + w[e]) { dist[v] = dist[u] + w[e]; if(!vis[v]) vis[v] = 1, q[++wei] = v; } } vis[u] = 0; } }
void Astar() { priority_queue <power> q; q.push( (power){S, 0, dist[S]} ); while(!q.empty()) { power u = q.top(); q.pop(); if(u.x == T) Ans[++num] = u.real; if(++Output[u.x] > k) continue; if(Output[T] == k) return; for(int e=first[u.x]; e; e=next[e]) { int v=go[e]; q.push( (power){v, u.real+w[e], dist[v]} ); } } }
int main() { n=get(); m=get(); k=get(); S=n, T=1; for(int i=1;i<=m;i++) { a[i].x=get(); a[i].y=get(); a[i].z=get(); Add(a[i].y, a[i].x, a[i].z); } SPFA(T);
memset(first,0,sizeof(first)); tot=0; for(int i=1;i<=m;i++) Add(a[i].x,a[i].y,a[i].z);
Astar();
for(int i=1;i<=k;i++) printf("%d\n",Ans[i]!=0?Ans[i]:-1);
}
|