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

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 } 
posted @ 2018-09-06 14:43  Refun  阅读(147)  评论(0编辑  收藏  举报