最短路径问题 3.Bellman-Ford算法
简要:Bellman-Ford算法计算的仍然是从一个点到其他所有点的最短路径算法,其时间复杂度是O(NE),N表示点数,E表示边数,不难看出,当一个图稍微稠密一点,边的数量会超过点数那么实际上效率是低于Dijkstra算法的。但是本算法可以计算存在负权边的情况(不存在负回路),因此可以用于更广泛的情况,但其实在日常解题应用中我们基本不会用到该算法,因为有一个比它效率更高的算法即SPFA算法,下一章会介绍到。SPFA算法其实是从Bellman-Ford算法演变而来的,那么从基础的开始,我们先来理解一下Bellman-Ford算法。
算法描述:s为起点,dis[v]为s到v的最短距离,pre[v]是v的前驱结点,w[j]是边 j 的长度,j 边的起点和终点分别是u,v。
1、初始化:dis[s]=0, dis[v]=∞(v≠s), pre[s]=0
2、for(i=1;i<=n-1;i++)
for(j=1;j<=e;j++)
if(dis[u]+w[j]<dis[v]){
dis[v]=dis[u]+w[j];
pre[v]=u;
}
算法理解:一开始已标记的点只有起点,每一次枚举所有的边,总会有一些边连接着已标记的点和未标记的点,即已经计算过最短距离和为计算过最短距离的点。因此每次枚举都会更新一些未标记的点成为已标记的点。而n-1次则保证了最坏情况下所有的点均可以被标记,即图的样子是一“串”的情况。
对于负权回路的情况,因为每一次枚举都会走过一圈负权回路,那么恰好在该回路两边的点之间的最短距离就会无限减小,因此会造成错误。对此,大家给出了一个不是解决方法的解决方法,就是如果在两重循环结束后,再次枚举每条边,如果再次出现某两点的距离减少,那么就返回"错误",已表示有负权回路,无法算出答案。
当然,对于负权回路也有解决方法,在介绍完SPFA算法后会补充一下。
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int n,e,s;
struct node{
int x;
int y;
int val;
}m[];
int dis[],pre[],a,b,w[][];
int bellmanford(int s){
int i,j; for(i=;i<=n;i++)
dis[i]=w[s][i];
dis[s]=;pre[s]=;
for(i=;i<=n-;i++)
for(j=;j<=e;j++)
if(dis[m[j].x]+m[j].val<dis[m[j].y])
{
dis[m[j].y]=dis[m[j].x]+m[j].val;
pre[m[j].y]=m[j].x;
}
for(j=;j<=e;j++){
if(dis[m[j].x]+m[j].val<dis[m[j].y]) return ;
}
return dis[]; }
int main(){
int i,j;
scanf("%d%d",&n,&e);
memset(dis,,sizeof(dis));
memset(w,,sizeof(w));
for(i=;i<=e;i++){
scanf("%d%d%d",&m[i].x,&m[i].y,&m[i].val);
a=m[i].x;
b=m[i].y;
w[a][b]=m[i].val;
}
for(i=;i<=;i++)
for(j=;j<=;j++)
printf("%d ",w[i][j]);
scanf("%d",&s);
printf("%d",bellmanford(s));
return ;
}
最短路径问题 3.Bellman-Ford算法的更多相关文章
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- 图论算法——最短路径Dijkstra,Floyd,Bellman Ford
算法名称 适用范围 算法过程 Dijkstra 无负权 从s开始,选择尚未完成的点中,distance最小的点,对其所有边进行松弛:直到所有结点都已完成 Bellman-Ford 可用有负权 依次对所 ...
- Dijkstra算法与Bellman - Ford算法示例(源自网上大牛的博客)【图论】
题意:题目大意:有N个点,给出从a点到b点的距离,当然a和b是互相可以抵达的,问从1到n的最短距离 poj2387 Description Bessie is out in the field and ...
- 图论之最短路径(2)——Bellman-Ford算法
继续最短路径!说说Bellman—Ford算法 思路:假设起点为s,图中有n个顶点和m个边,那么它到任一点(比如i)的最短路径 最多可以有n-1条(没有回路就是n-1条):因为最短路径中不可能包含回路 ...
- poj1860 bellman—ford队列优化 Currency Exchange
Currency Exchange Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 22123 Accepted: 799 ...
- uva 558 - Wormholes(Bellman Ford判断负环)
题目链接:558 - Wormholes 题目大意:给出n和m,表示有n个点,然后给出m条边,然后判断给出的有向图中是否存在负环. 解题思路:利用Bellman Ford算法,若进行第n次松弛时,还能 ...
- ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)
两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...
- 最短路径—Dijkstra算法和Floyd算法
原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最后边附有我根据文中Dijkstra算法的描述使用jav ...
- 最短路径—Dijkstra算法和Floyd算法【转】
本文来自博客园的文章:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算法 1.定义概览 Dijk ...
随机推荐
- java带jar包的命令行运行
运行有些java类需要第三方的jar包(lib),在用命令行运行时本人总结如下几个方法: 方法一.编译 javac -cp D:\lab\googleapi.jar Lab.java设置classp ...
- PHP腾讯与百度坐标转换
function coordinate_switch($a,$b){//百度转腾讯坐标转换 $a = Latitude , $b = Longitude $x = (double)$b - 0.006 ...
- JavaMelody监控spring、struts
前言 前面讲过了Javamelody的基本配置,如何使用Javamelody来监控JDBC以及SQL. 这里继续讲解一下如何监控struts和spring. 手码不易,转载请注明:xingoo 由于s ...
- 4.Zabbix 3.0 案例
请查看我的有道云笔记: http://note.youdao.com/noteshare?id=2807c0910cd63d309e1462128a31ae0e&sub=241A94E5717 ...
- May 24th 2017 Week 21th Wednesday
Always remember that you are absolutely unique. 永远记住,你是独一无二的. I am unique, in the way that all I do ...
- 因子和&&因子数
给定一数n,求n的因子数目和因子之和 上述求因子和式子等于 ∏{(piei+1 - 1) / (pi - 1)} (∏就是连乘) 模板: +; int prime[maxn]; bool is_pr ...
- 七、IntelliJ IDEA 常见文件类型的图标介绍
咱们已经了解了很多关于 IntelliJ IDEA 的内容啦,例如,在 Windows 系统下安装 IntelliJ IDEA.运行 IntelliJ IDEA .创建 Java 项目以及修改 Int ...
- 构建Linux根文件系统(未完待续)
所谓制作根文件系统, 就是创建各种目录, 并且在里面创建各种文件. 比如在/bin ./sbin 目录下存放各种可执行程序, 在/etc 目录下存放配置文件, 在/lib 目录下存放库文件 ...
- Oracle数据库中游标的游标的使用
本人不喜欢说概念啥的,就直接说明使用方法吧 案例1: DECALRE --声明游标 CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE ...
- dual表详解
dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户 SQL> select user from ...