题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式

输入格式:

 

第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

 

输出格式:

 

一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

 

输入输出样例

输入样例#1:
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出样例#1:
0 2 4 3

说明

时空限制:1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=15

对于40%的数据:N<=100,M<=10000

对于70%的数据:N<=1000,M<=100000

对于100%的数据:N<=10000,M<=500000

样例说明:

【模板】单源最短路径*

思路:SPFA or Dijkstra

此题是有向边!!!(然而我并没有被这里坑)

SPFA

初始化最短路径表;

源点入队;

取出队首点;

枚举取出点的边;

如果能松弛,就松弛,并把被松弛的点加入队列;

如此循环直到队列为空。

另外,根据2183ms的亲测,使用优先队列应该没有明显优化效果(可能更稳定了,我不太懂)。

Dijkstra

初始化最短路径表;

源点标记;

用源点的边松弛;

寻找距离最短的未被标记的点;

用这个点的边松弛;

如此循环n-1次。

虽然Dijkstra大部分时候不如SPFA快,但理论是Dijkstra更稳定。

代码实现

769ms的SPFA:

 1 #include<cstdio>
 2 int n,m,s,v[10010];
 3 int a,b,c;
 4 int q[500010],head,tail;
 5 int h[10010],hs;
 6 struct edge{int s,n,v;}e[500010];
 7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; }
 8 int main(){
 9     scanf("%d%d%d",&n,&m,&s);
10     for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;
11     for(int i=1;i<=m;i++){
12         scanf("%d%d%d",&a,&b,&c);
13         e[++hs]=(edge){b,h[a],c};
14         h[a]=hs;
15     }
16     q[head++]=s;
17     while(head>tail){
18         a=q[tail++];
19         for(int i=h[a];i;i=e[i].n){
20             if(rel(v[e[i].s],v[a],e[i].v)){
21                 q[head++]=e[i].s;
22                 v[e[i].s]=v[a]+e[i].v;
23             }
24         }
25     }
26     for(int i=1;i<=n;i++) printf("%d ",v[i]);
27     return 0;
28 }
 1 #include<queue> 
 2 #include<cstdio>
 3 using namespace std;
 4 int n,m,s,v[10010];
 5 int a,b,c;
 6 priority_queue <int> q;
 7 int h[10010],hs;
 8 struct edge{int s,n,v;}e[500010];
 9 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; }
10 int main(){
11     scanf("%d%d%d",&n,&m,&s);
12     for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;
13     for(int i=1;i<=m;i++){
14         scanf("%d%d%d",&a,&b,&c);
15         e[++hs]=(edge){b,h[a],c};
16         h[a]=hs;
17     }
18     q.push(s);
19     while(!q.empty()){
20         a=q.top();
21         q.pop();
22         for(int i=h[a];i;i=e[i].n){
23             if(rel(v[e[i].s],v[a],e[i].v)){
24                 q.push(e[i].s);
25                 v[e[i].s]=v[a]+e[i].v;
26             }
27         }
28     }
29     for(int i=1;i<=n;i++) printf("%d ",v[i]);
30     return 0;
31 }
2183ms优先队列(STL)优化的SPFA

相关文章: