BZOJ3245:最快路线(最短路)
Description
精明的小R每每开车出行总是喜欢走最快路线,而不是最短路线.很明显,每条道路的限速是小R需要考虑的关键问题.不过有一些限速标志丢失了,于是小R将不知道能开多快.不过有一个合理的方法是进入这段道路时不改变速度行驶.你的任务就是计算从小R家(0号路口)到D号路口的最快路线.
现在你得到了这个城市的地图,这个地图上的路都是单向的,而且对于两个路口A和B,最多只有一条道路从A到B.并且假设可以瞬间完成路口的转弯和加速.
Input
第一行是三个整数N,M,D(路口数目,道路数目,和目的地). 路口由0...N-1标号
接下来M行,每行描述一条道路:有四个整数A,B,V,L,(起始路口,到达路口,限速,长度) 如果V=0说明这段路的限速标志丢失.
开始时你位于0号路口,速度为70.
Output
仅仅一行,按顺序输出从0到D经过的城市.保证最快路线只有一条.
Sample Input
6 15 1
0 1 25 68
0 2 30 50
0 5 0 101
1 2 70 77
1 3 35 42
2 0 0 22
2 1 40 86
2 3 0 23
2 4 45 40
3 1 64 14
3 5 0 23
4 1 95 8
5 1 0 84
5 2 90 64
5 3 36 40
0 1 25 68
0 2 30 50
0 5 0 101
1 2 70 77
1 3 35 42
2 0 0 22
2 1 40 86
2 3 0 23
2 4 45 40
3 1 64 14
3 5 0 23
4 1 95 8
5 1 0 84
5 2 90 64
5 3 36 40
Sample Output
0 5 2 3 1
HINT
【数据范围】
30% N<=20
100% 2<=N<=150;0<=V<=500;1<=L<=500
Solution
dis[i][j]表示到i点速度为j的最短时间
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 using namespace std; 5 6 struct Edge{int to,next,len,v;}edge[200009]; 7 struct Node{int p,v;}t,pre[209][509]; 8 int n,m,tar,u,v,l,c,used[209][509]; 9 double dis[209][509],ans=1e17; 10 int head[209],num_edge,maxv; 11 queue<Node>q; 12 13 void add(int u,int v,int l,int c) 14 { 15 edge[++num_edge].to=v; 16 edge[num_edge].next=head[u]; 17 edge[num_edge].len=l; 18 edge[num_edge].v=c; 19 head[u]=num_edge; 20 } 21 22 void SPFA() 23 { 24 for (int i=0; i<=150; ++i) 25 for (int j=0; j<=500; ++j) dis[i][j]=1e17; 26 dis[0][70]=0; used[0][70]=true; 27 t.p=0; t.v=70; q.push(t); 28 while (!q.empty()) 29 { 30 Node x=q.front(); q.pop(); 31 for (int i=head[x.p]; i; i=edge[i].next) 32 { 33 int sp=edge[i].v==0?x.v:edge[i].v; 34 if (dis[x.p][x.v]+1.0*edge[i].len/sp<dis[edge[i].to][sp]) 35 { 36 dis[edge[i].to][sp]=dis[x.p][x.v]+1.0*edge[i].len/sp; 37 pre[edge[i].to][sp]=x; 38 if (!used[edge[i].to][sp]) 39 { 40 used[edge[i].to][sp]=true; 41 t.p=edge[i].to; t.v=sp; q.push(t); 42 } 43 } 44 } 45 used[x.p][x.v]=false; 46 } 47 } 48 49 void Print(int x,int v) 50 { 51 if (pre[x][v].p) Print(pre[x][v].p,pre[x][v].v); 52 printf(" %d",x); 53 } 54 55 int main() 56 { 57 scanf("%d%d%d",&n,&m,&tar); 58 for (int i=1; i<=m; ++i) 59 { 60 scanf("%d%d%d%d",&u,&v,&c,&l); 61 add(u,v,l,c); 62 } 63 SPFA(); 64 for (int i=0; i<=500; ++i) 65 ans=min(ans,dis[tar][i]); 66 for (int i=0; i<=500; ++i) 67 if (dis[tar][i]==ans) 68 printf("0"),Print(tar,i); 69 }