这个算法也是求单源最短路径用的,但是这个算法可以解决Dijkstra不能解决的负权边问题。

算法要点:

1、用dis存放源点到任意一点的距离。

2、用三个数组存放输入的点到点以及点到点的距离,x【i】,y【i】,x_y_dis【i】其中表示x【i】到y【i】的距离为x_y_dis【i】。

3、循环边数,比较dis【y【i】】和dis【x【i】】+ x_y_dis【i】,然后更新dis【y【i】】,意思和Dijkstra很像,就是源点到y点的距离如果大于源点到x的距离加上x到y的距离就更新。//注意这里是y在dis前面,因为y是目的点,x到y是有方向的。

4、最外面循环点数,注意要循环N-1个点,因为N个点最短距离的最大边数不能超过N-1。

5、设置两个标识去标志,已经不能松弛了,尽早跳出循环,图有负权环路(只是进行优化处理,在模型中就不写出了)

算法模型:

for(点数-1)

{

for(边数)

{

if(dis【y【i】】> dis【x【i】】+ x_y_dis【i】)

dis【y【i】】= dis【x【i】】+ x_y_dis【i】)

}

}

算法的核心:

最外面循环第一次意思是,找到源点到目的地,经过一条边也就是进过输入时的纯x_y_dis距离比现在的距离小,那么进行松弛。

第二次循环就是,经过两条边之后的优化,因为经过一条边的最小值已经在第一次循环保存进dis中了,所以是经过两条边。

这也就很好解释为啥是N-1次循环,因为如果N个点,有N条边那一定肯定其中有回路了。

也就很好解释了为什么标识能过提前跳出循环,因为如M边的循环不能松弛的话,那么加上M+1条边就不可能再松弛了。

#include<cstdio>
#include<cstdlib>
#include<iostream> using namespace std;
/*Bellman-Ford*/ int dis[];
int x[];
int y[];
int x_y_dis[];
const int MAX = ;//定义一个最大值,距离不会超过这个 int main()
{
int i,j,q;//循环变量
int n,m;
int check=;//当这个标记为1时代表重复了,已经不能松弛了,尽早跳出循环
int flag=;//当这个标记为1时代表这个图有负权环路
cin>>n>>m;//输入N*N的图,和M条边对应的值 for (i = ; i <= n; i++)//初始化dis距离
dis[i] = MAX; for (i = ; i <= m; i++)
{
cin>>x[i]>>y[i]>>x_y_dis[i];//输入x到y的距离为z
} dis[] = ;//自己到自己肯定是0 for (q = ; q <= n-; q++)//注意最外面的循环是循环的总的点数减一个,因为两个点最多包含N-1条边
{
check = ;//如果循环结束还是1则证明没有松弛任何一个值
for (i = ; i <= m; i++)
{
if(dis[y[i]] > dis[x[i]] + x_y_dis[i])
{
dis[y[i]] = dis[x[i]] + x_y_dis[i];
check = ;
}
}
if(check == )//如果不能松弛任何一个值,那么跳出循环
break;
} if(check == )//只有最后一次循环还是有松弛的情况下才有可能出现无限松弛的负权环路
{
check=;
//判断是否有负权环路
for (i = ; i <= m; i++)
{
if(dis[y[i]] > dis[x[i]] + x_y_dis[i])
{
dis[y[i]] = dis[x[i]] + x_y_dis[i];
check = ;
}
if(check == )
break;
}
if(check == )
{
cout<<"这个图有负权回路,没有最短路径"<<endl;
}
} if(check != )//经过上面的判断只有如果没有负权回路,就输出
{
for (i = ; i <= n; i++)
{
cout<<dis[i]<<" ";
}
cout<<endl;
}
else
return ; } /* 6 9
1 2 1
1 3 12
2 3 9
2 4 3
3 5 5
4 3 4
4 5 13
4 6 15
5 6 4
Result:0 1 8 4 13 17 5 5
2 3 2
1 2 -3
1 5 5
4 5 2
3 4 3
Result:0 -3 -1 2 4
*/

最后想提的是,这个算法的时间复杂度是O(NM)也就是当M特别多的时候(题目故意恶心你)需要进一步的优化处理,我之后再实现。

但是这个算法的优点就是能解决负边权的问题。

和Dijkstra相比,Dijkstra是在两个点之间加一个点,利用点去循环更新一个距离之后就认为这个距离已经是最优解了,后面利用最优解去不断取出后面点的最优解。而Bellman-Ford是循环输入的边,让边的不断增加去更新距离,所以当边不断的增加,距离也就更新了,无论你距离的正负。

最短路径算法专题3----Bellman-Ford的更多相关文章

  1. 最短路径算法专题2----Dijkstra

    这个算法适用于求单源最短路径,从一点出发,到其余个点的最短路径. 算法要点: 1.用二维数组存放点到点的距离-----不能相互到达的点用MAX代替距离 2.用dis数组存放源点到任意其他一点的距离-- ...

  2. Bellman—Ford算法思想

    ---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...

  3. Bellman - Ford 算法解决最短路径问题

    Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...

  4. ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

    两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...

  5. Johnson 全源最短路径算法

    解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...

  6. Floyd-Warshall 全源最短路径算法

    Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...

  7. Bellman-Ford 单源最短路径算法

    Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...

  8. poj1860 bellman—ford队列优化 Currency Exchange

    Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22123   Accepted: 799 ...

  9. uva 558 - Wormholes(Bellman Ford判断负环)

    题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...

随机推荐

  1. zonghe

      package hcxAction; import hcxMode.Advertises; import hcxMode.Areas; import hcxMode.Saveresume; imp ...

  2. POJ 1696 Space Ant 极角排序(叉积的应用)

    题目大意:给出n个点的编号和坐标,按逆时针方向连接着n个点,按连接的先后顺序输出每个点的编号. 题目思路:Cross(a,b)表示a,b的叉积,若小于0:a在b的逆时针方向,若大于0a在b的顺时针方向 ...

  3. 欧几里得算法求最大公约数(gcd)

    关于欧几里得算法求最大公约数算法, 代码如下: int gcd( int a , int b ) { if( b == 0 ) return a ; else gcd( b , a % b ) ; } ...

  4. Tenured 区并发垃圾回收器CMS介绍

    当使用CMS收集器时,当开始进行收集时,old代的收集过程如下所示:1,首先jvm根据-XX:CMSInitiatingOccupancyFraction,-XX:+UseCMSInitiatingO ...

  5. Linux平台从文件中查找字符赋值于变量

    以telnet方式登录Linux主机,在默认目录下用命令创建一个包含DUT wanIP的文本文件.[root] echo wanIP=88.0.100.253 > ./wanIP.txt在默认目 ...

  6. 测试TCP/IP配置

    安装网络硬件和网络协议之后,我们一般要进行TCP/IP协议的测试工作,那么怎样测试才算是比较全面的测试呢?我们认为,全面的测试应包括局域网和互联网两个方面,因此应从局域网和互联网两个方面测试,以下是我 ...

  7. http?https?相对协议?

    1 1 1 将CDN 上所有链接的协议默认设置为“相对协议”,也就是链接以 // 开头,前面去掉了 http: 或 https: 字样, 这样做的好处是浏览器能够根据你的网站所采用的协议来自动加载 C ...

  8. HDU2673:shǎ崽 OrOrOrOrz

    Problem Description Acmer in HDU-ACM team are ambitious, especially shǎ崽, he can spend time in Inter ...

  9. 【Machine Learning in Action --2】K-近邻算法改进约会网站的配对效果

    摘自:<机器学习实战>,用python编写的(需要matplotlib和numpy库) 海伦一直使用在线约会网站寻找合适自己的约会对象.尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的 ...

  10. JPG、PNG和GIF图片的基本原理及优化方法

    一提到图片,我们就不得不从位图开始说起,位图图像(bitmap),也称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的.这些点可以进行不同的排列和染色以构成一副图片.当放大位图时,可以看见 ...