Bellman-Ford算法 - 有向图单源最短路径

时间:2023-03-09 09:13:48
Bellman-Ford算法 - 有向图单源最短路径

2017-07-27  08:58:08

writer:pprp

参考书目:张新华的《算法竞赛宝典》

Bellman-Ford算法是求有向图单源最短路径的,dijkstra算法的条件是图中任意一条边的权都是正的;BF算法可以解决存在负边权的图;

算法流程分为三个部分:

  1. 初始化,将除源点外的所有顶点的最短距离的估计值D[i] = +无穷,D[sourse] = 0;
  2. 迭代求解:反复对每条边进行松弛操作,使得每个顶点的最短距离D[i]估计值主讲逼近其最短距离;运行n-1次
  3. 检验负权回路:通过松弛操作判断每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回FALSE表名问题无解;否则返TRUE,输出D[i]的值

例题:虫洞

代码如下:

#include <iostream>

using namespace std;

int w[][],d[];
int n,m; //n 是点的个数, m是边的个数
int change; //? void init()
{
cin >> n >> m;
int x,y,v;
for(int i = ; i <= n ; i++)
for(int j = ; j <=n; j++)
w[i][j] = INT_MAX;
for(int i = ; i <= m; i++)
{
cin >> x >> y >> v;
w[x][y] = v;//单向通道,边的权值为v
}
} void bellman_ford(int x)
{
int i,j,k;
for(i=; i<=n; i++) //initial array d
d[i] = w[x][i];
d[x] = ; //到自己距离为0
for(k=; k<=n-; k++)
for(j = ; j >=n ; j++) //松弛
for(i = ; i <=n ; i++)
if((w[i][j]!=INT_MAX)&&d[i]!=INT_MAX&&d[j]>d[i]+w[i][j])
d[j] = d[i]+w[i][j];
change = ;
for(i =; i<=n; i++) //松弛操作判断是否存在负权回路
for(j=; j<=n; j++)
if(w[i][j]!=INT_MAX&&d[i]!=INT_MAX&&d[j]>d[i]+w[i][j])
change = ;
if(change)
cout <<"Not possoble"<<endl;
else
cout <<"Possible"<<endl;
} int main()
{
init();
bellman_ford();
return ;
}