贝尔曼福特(bellman_ford)
作者:互联网
核心:两层循环:
问:为什么要循环n-1次
答:有n个点,若求a到b的最短路径,至多经过n-1个点(不能是回路)
贝尔曼福特不能解决负权回路问题:
如果为负权回路:每次判断是否松弛操作时,都有dis[u[i]]+w[i]<dis[v[i]]
因此每次都会减小,从而无法正确的求出最短路径
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1000; 4 const int inf=0x3f3f3f3f; 5 int w[maxn],u[maxn],v[maxn],dis[maxn],back[maxn]; 6 int check; 7 int m,n; 8 void dfs(int back[],int k) 9 { 10 if(back[k]==k) 11 { 12 cout<<k<<" "; 13 return; 14 } 15 dfs(back,back[k]); 16 cout<<k<<" "; 17 return; 18 } 19 void Bellman_Ford() 20 { 21 for(int i=1;i<=n;i++) 22 { 23 back[i]=i; 24 dis[i]=inf; 25 } 26 dis[1]=0; 27 for(int j=1;j<=n-1;j++) 28 { 29 check=0; 30 for(int i=1;i<=m;i++) 31 { 32 if(dis[u[i]]!=inf&&dis[v[i]]>dis[u[i]]+w[i]) 33 { 34 dis[v[i]]=dis[u[i]]+w[i]; 35 back[v[i]]=u[i]; 36 check=1; 37 } 38 } 39 if(check==0) 40 break; 41 } 42 } 43 int main() 44 { 45 int flag=0; 46 cin>>n>>m; 47 for(int i=1;i<=m;i++) 48 { 49 cin>>u[i]>>v[i]>>w[i]; 50 } 51 Bellman_Ford(); 52 for(int j=1;j<=n-1;j++) 53 { 54 for(int i=1;i<=m;i++) 55 { 56 if(dis[v[i]]>dis[u[i]]+w[i]) 57 { 58 flag=1; 59 break; 60 } 61 } 62 } 63 if(flag==1) 64 cout<<"有负权回路"<<endl; 65 else 66 { 67 for(int i=1;i<=n;i++) 68 { 69 cout<<"1号顶点到"<<i<<"号顶点的最短距离为"<<dis[i]<<endl; 70 } 71 cout<<"1号节点到5号节点的路径为:"; 72 dfs(back,5); 73 } 74 return 0; 75 }
用队列优化贝尔曼福特算法:
队列优化后的bf算法,遇到负权回路会死循环
注释内是用数组模拟队列的方法
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxn=10001; 5 int u[maxn],v[maxn],w[maxn]; 6 int first[maxn],next[maxn],book[maxn]; 7 //int que[maxn]; 8 int dis[maxn]; 9 int n,m,k;//head=1,tail=1; 10 queue<int> q; 11 void bellman_ford() 12 { 13 //que[tail]=1; 14 //tail++; 15 q.push(1); 16 book[1]=1; 17 dis[1]=0; 18 while(/*head<tail*/!q.empty()) 19 { 20 //k=first[que[head]]; 21 k=first[q.front()]; 22 while(k!=-1) 23 { 24 if(dis[v[k]]>dis[u[k]]+w[k]) 25 { 26 dis[v[k]]=dis[u[k]]+w[k]; 27 28 if(book[v[k]]==0) 29 { 30 //que[tail]=v[k]; 31 //tail++; 32 q.push(v[k]); 33 book[v[k]]=1; 34 } 35 k=next[k]; 36 } 37 } 38 //que[head]=0; 39 //head++; 40 q.pop(); 41 } 42 } 43 int main() 44 { 45 fill(first,first+10001,-1); 46 fill(dis,dis+10001,inf); 47 cin>>n>>m; 48 for(int i=1;i<=m;i++) 49 { 50 cin>>u[i]>>v[i]>>w[i]; 51 next[i]=first[u[i]]; 52 first[u[i]]=i; 53 } 54 bellman_ford(); 55 for(int i=1;i<=n;i++) 56 { 57 cout<<dis[i]<<" "; 58 } 59 return 0; 60 }
无负权回路:
有负权回路:
标签:int,bellman,ford,tail,maxn,贝尔曼,first,负权,dis 来源: https://www.cnblogs.com/inawaken/p/16213159.html