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 ' ' 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 }