1 //spfa在正权边题目容易被卡,所以正权边的情况下还是用dijkstra吧
2 //spfa比dijkstra的优点是可以判负环,处理负权边
3 //spfa的时间复杂度为(O(|V||E|))
4 //spfa是求单元最短路
5 //spfa在最小费用最大流中常用
6
7 #include<cstdio>
8 #include<cstring>
9 #include<cmath>
10 #include<queue>
11 #include<algorithm>
12 #include<iostream>
13 using namespace std;
14 typedef long long ll;
15 #define endl '\n'
16 const int maxn = 10100;//最大顶点数
17 const int maxm = 500500;//最大边数
18 const int inf = 0x3f3f3f3f;
19 struct edge{
20 int to,nxt,w;
21 }e[maxn];
22
23 int using_v[maxn],using_times[maxn];//入队的点和点的入队次数
24 int head[maxn],dis[maxn];
25 int cnt=0;
26 int n,m; //n个点m条边
27
28 void addedge(int u,int v,int w){
29 e[cnt].to=v;
30 e[cnt].w=w;
31 e[cnt].nxt=head[u];
32 head[u]=cnt++;
33 }
34
35 int spfa(int start){
36 queue<int>q;
37 dis[start]=0; //起始点离自己的dis为0
38 using_v[start]=1; //起始点标记
39 q.push(start); //入队
40 while( !q.empty()){
41 int top=q.front();
42 q.pop();
43 using_v[top]=0;
44 if( using_times[top]>n ) return 0; //存在负环
45 for(int i=head[top];~i;i=e[i].nxt){
46 if( dis[e[i].to]>dis[top]+e[i].w){
47 dis[e[i].to]=dis[top]+e[i].w;
48 if( !using_v[e[i].to] ){
49 using_v[e[i].to]=1; //入队
50 q.push(e[i].to);
51 }
52 }
53 }
54 }
55 return 1;
56 }
57
58 int main()
59 {
60 int u,v,w,s;//u--->v的权值为w,s为起点
61 cin>>n>>m>>s;
62 memset(dis,0x3f,sizeof(dis));
63 memset(head,-1,sizeof(head));
64 for(int i=0;i<m;i++){
65 cin>>u>>v>>w;
66 addedge(u,v,w);
67 }
68 spfa(s);
69 for(int i=1;i<=n;i++){
70 if( dis[i]!=inf ){
71 cout<<dis[i]<<endl;
72 }else{
73 cout<<"inf"<<endl;
74 }
75 }
76 return 0;
77 }