ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

贝尔曼福特(bellman_ford)

2022-05-01 16:31:06  阅读:178  来源: 互联网

标签:int bellman ford tail maxn 贝尔曼 first 负权 dis


核心:两层循环:

问:为什么要循环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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有