bellman-ford算法 最短路
2017-04-16 09:47
323 查看
重要应用:在负权的图的单源最短路问题
Bellman-Ford 算法和 Dijkstra 算法都是可以解决单源最短路径的算法,一个实现的很好的 Dijkstra 算法比 Bellman-Ford 算法的运行时间要低,但dijkstra算法无法解决存在负权环的图的单源最短路问题(因为dijkstra算法每循环一次,确定一条到某个顶点的最短路,之所以能确定,是因为每条边都是正值,若到达其他顶点的最短路经过该顶点,则最短路总权值会更大)。
Bellman-Ford 算法描述:
如求下图单源最短路径,以1为源点,求到各顶点的最短路径,黑色代表权值,红色代表第几条边(是第几条边在实际中会不同,这里是假设 )
1.初始化:
将除源点外的所有顶点的最短距离估计值 d[v] =+∞,源顶点距离为 0;
2.迭代求解计算最短路径:
执行 V - 1 次 (遍历一条最短路径经过的点最多是v-1个嘛,所有松弛|v|-1次后最短路必然会出现!);
反复对边集e中的每条边进行松弛操作,(即如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d),使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;
第一次循环:
从第一条边开始到第十条边进行松弛操作;
得到下图:
第二次循环:
也是从第一条边开始到第十条边进行松弛操作;与上面同理;
得到如图;
第三次循环:
也是从第一条边开始到第十条边进行松弛操作;与上面同理;
因为第三次循环发现任何没有任何一个更新,说明到各个顶点的最短路都已经找到,break;跳出循环,结束
3.检验负权回路:
遍历图中的所有边,计算 u 至 v 的距离,如果对于 v 存在更小的距离,则说明存在环(因为经过上面步骤二, 如果不存在负环,则到各点的最短路已经确定);
代码:无路径
有路径输出:
Bellman-Ford 算法和 Dijkstra 算法都是可以解决单源最短路径的算法,一个实现的很好的 Dijkstra 算法比 Bellman-Ford 算法的运行时间要低,但dijkstra算法无法解决存在负权环的图的单源最短路问题(因为dijkstra算法每循环一次,确定一条到某个顶点的最短路,之所以能确定,是因为每条边都是正值,若到达其他顶点的最短路经过该顶点,则最短路总权值会更大)。
Bellman-Ford 算法描述:
如求下图单源最短路径,以1为源点,求到各顶点的最短路径,黑色代表权值,红色代表第几条边(是第几条边在实际中会不同,这里是假设 )
1.初始化:
将除源点外的所有顶点的最短距离估计值 d[v] =+∞,源顶点距离为 0;
2.迭代求解计算最短路径:
执行 V - 1 次 (遍历一条最短路径经过的点最多是v-1个嘛,所有松弛|v|-1次后最短路必然会出现!);
反复对边集e中的每条边进行松弛操作,(即如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d),使得顶点集V中的每个顶点v的最短距离估计值逐步逼近其最短距离;
第一次循环:
从第一条边开始到第十条边进行松弛操作;
得到下图:
第二次循环:
也是从第一条边开始到第十条边进行松弛操作;与上面同理;
得到如图;
第三次循环:
也是从第一条边开始到第十条边进行松弛操作;与上面同理;
因为第三次循环发现任何没有任何一个更新,说明到各个顶点的最短路都已经找到,break;跳出循环,结束
3.检验负权回路:
遍历图中的所有边,计算 u 至 v 的距离,如果对于 v 存在更小的距离,则说明存在环(因为经过上面步骤二, 如果不存在负环,则到各点的最短路已经确定);
for(i=1;i<=enum;i++) //检查有无负权环 { if(d[edge[i].v]>dis[e[i].u]+edge[i].w) { flag = false;//存在负环 break; } }
代码:无路径
#include<stdio.h> #include<string.h> #define Max 99999 int m,n,d[10000];//n条边 struct Edge{ int u; int v; int w; }e[10000]; bellmenford(int root){ int i,j,k; for(i=1;i<=m;i++){ d[i]=Max; } d[root]=0; for(k=0;k<m-1;k++){//循环k-1次 for(i=1;i<=n;i++){//循环每条边 if(d[e[i].v]>d[e[i].u]+e[i].w){//如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d d[e[i].v]=d[e[i].u]+e[i].w; } } } for(i=1;i<=n;i++){//判断负环 if(d[e[i].v]>d[e[i].u]+e[i].w){ printf("NO"); return 0; } } for(i=1;i<=m;i++){ printf("%d ",d[i]); } } int main(){ int i,j,k=1; scanf("%d%d",&m,&n); for(i=1;i<=n;i++){ scanf("%d%d%d",&e[k].u,&e[k].v,&e[k].w); k++; } bellmenford(1); return 0; }
有路径输出:
#include<stdio.h> #include<string.h> #define Max 99999 int m,n,d[10000],pre[10000];//n条边,d[]表示到某顶点的总权值,pre[]记录路径 struct Edge{ int u; int v; int w; }e[10000]; bellmenford(int root){ int i,j,k; for(i=1;i<=m;i++){ d[i]=Max; pre[i]=root;//初始化到各顶点的路径的起点为源点 } d[root]=0; for(k=0;k<m-1;k++){//循环k-1次 for 4000 (i=1;i<=n;i++){//循环每条边 if(d[e[i].v]>d[e[i].u]+e[i].w){//如果起点 u 的距离 d 加上边的权值 w 小于终点 v 的距离 d,则更新终点 v 的距离值 d d[e[i].v]=d[e[i].u]+e[i].w; pre[e[i].v]=e[i].u;//到v点经过u点 } } } for(i=1;i<=n;i++){//判断负环 if(d[e[i].v]>d[e[i].u]+e[i].w){ printf("NO"); return 0; } } for(i=1;i<=m;i++){ printf("%d %d ",d[i],i); j=i; while(pre[j]!=root){ printf("%d ",pre[j]); j=pre[j]; } if(i!=root)printf("%d",root); printf("\n"); } } int main(){ int i,j,k=1; scanf("%d%d",&m,&n); for(i=1;i<=n;i++){ scanf("%d%d%d",&e[k].u,&e[k].v,&e[k].w); k++; } bellmenford(1); return 0; }
相关文章推荐
- hdu 2544 最短路 (Bellman_Ford算法)
- poj1860 【最短路&&bellman_ford算法】
- HDU 2544 最短路 Dijkstra 算法、 Floyd 算法 Bellman_ford算法
- 最短路之bellman-ford算法
- poj 3259 最短路判负环 spfa算法和Bellman_ford算法
- 最短路--Bellman-Ford算法
- 最短路-Bellman-Ford算法
- C--最短路(Bellman-Ford算法)
- [算法与数据结构] - No.10 图论(3)- 最短路Dijkstra算法、Bellman-Ford算法和Floyd算法
- 最短路bellman-ford算法)B - 畅通工程续
- bellman-ford算法(最短路、最短路劲)
- [单源最短路]Bellman-Ford算法
- poj 1860 最短路—Bellman-Ford算法
- 最短路——Bellman-Ford算法
- 最短路问题 Bellman-Ford算法
- POJ - 2240 Arbitrage (最短路 Floyd算法 && Bellman-Ford算法)
- 最短路 bellman-ford算法
- POJ-3259 Wormholes(最短路 Bellman-Ford算法)
- 单源最短路 bellman_ford算法(模板)
- 最短路的Bellman-Ford算法 【判断有无负权环】