Bellman-Ford算法和SPFA算法
Belloman-Ford算法
算法介绍
Dijkstra可以解决单源无负边最短路径问题。但是当遇到含有负边的单源最短路径问题就需要使用Bellman-Ford算法来解决。Bellman-Ford算法还可以检测出负环。
算法步骤
- 源点s,数组d[u]d[u]d[u]表示s到u的最短距离
- 初始化:d[s]=0d[s]=0d[s]=0,∀v∈V−{s},d[v]=∞\forall v \in V-\{s\},d[v]=\infin∀v∈V−{s},d[v]=∞
- 循环∣V∣−1|V|-1∣V∣−1次,每次对每条边进行松弛操作:对于有向边(u,v)(u,v)(u,v),如果d[u]+w[u,v]<d[v]d[u]+w[u,v]<d[v]d[u]+w[u,v]<d[v],则d[v]=d[u]+w[u,v]d[v]=d[u]+w[u,v]d[v]=d[u]+w[u,v]
- 对每条边进行松弛操作,如果操作成功,说明有负环。否则最后的d[i]d[i]d[i]就是源点s到i的最短路径长度
我们可以看到Bellman-Ford算法的算法结构是比较简单的,复杂度是O(VE)O(VE)O(VE),比Dijkstra算法最好为O(E+VlogV)O(E+VlogV)O(E+VlogV)大,但是可以处理负边。
正确性证明
可以看到算法的核心操作就是松弛。这就要用到另一篇博客中介绍Dijkstra算法的时候的几个关于松弛操作的引理,这里就不再进行证明,如果想要看证明可以移步:传送门。
设源点为s,d[u]表示源点到u的最短路径,w[u,v]表示从点u到点v的一条有向边的长度,δ(u,v)\delta(u,v)δ(u,v)表示u到v的最短路径。
最优子结构:任意两点之间的最短路径的子路径仍然是最短路径
引理1:初始化以后∀v∈V,d[u]⩾δ(s,v)\forall v \in V,d[u]\geqslant\delta(s,v)∀v∈V,d[u]⩾δ(s,v)
引理2:假设存在s到v的最短路径:s->…->u->v,d[u]=δ(s,u)d[u]=\delta(s,u)d[u]=δ(s,u),那么在对边(u,v)进行松弛操作以后d[v]=δ(s,v)d[v]=\delta(s,v)d[v]=δ(s,v)
假设没有负边环,那么:
- 对于初始情况,d[s]=0=δ(s,s)d[s]=0=\delta(s,s)d[s]=0=δ(s,s)
因为如果d[s]<0d[s]<0d[s]<0说明存在一个环s->…->s的权值和为负,而假设没有负边环,所以不存在这样的情况
- 假设对于最短路径经过边数为k的点u在第k次循环d[u]=δ(s,u)d[u]=\delta(s,u)d[u]=δ(s,u),那么由引理2,所有最短路径经过边数为k+1的点v在第k+1次循环后,d[v]=δ(s,v)d[v]=\delta(s,v)d[v]=δ(s,v)
- 因为一个节点数目为∣V∣|V|∣V∣的图的简单路径最长为∣V∣−1|V|-1∣V∣−1,所以∣V∣−1|V|-1∣V∣−1次循环以后∀v∈V,d[v]=δ(s,v)\forall v \in V,d[v]=\delta(s,v)∀v∈V,d[v]=δ(s,v)
- 第|V|次循环应该无法进行松弛操作。
如果第|V|次循环可以进行松弛操作,则由逆反命题,说明有负边环。
证毕。
SPFA算法
算法介绍
SPFA算法是对Bellman-Ford算法的优化。因为Bellman-Ford算法中会对已经确定最短路径的点进行松弛判断,但这实际上是不必要的。我们需要松弛的是被松弛的点可以到达的点。正是这种思想我们有了SPFA算法。
算法步骤
- 源点s,数组d[u]d[u]d[u]表示s到u的最短距离,队列Q表示需要操作进行松弛操作的点的集合
- 初始化:d[s]=0,∀v∈V−{s},d[v]=∞d[s]=0,\forall v \in V-\{s\},d[v]=\infind[s]=0,∀v∈V−{s},d[v]=∞,将点s加入Q中
- 从Q中取出一个点,对它可以到达的点进行松弛操作,并将成功进行松弛操作的点加入Q中
- 重复上述步骤直到Q为空
- 如果某个点被松弛了|V|次,说明有负边环
正确性证明
同Bellman-Ford算法,可以用归纳法进行证明。本质上SPFA算法提取出了Bellman-Ford算法中有效的操作。
复杂度分析
可以构造图使得算法复杂度为O(VE)O(VE)O(VE),因此算法的最坏复杂度为O(VE)O(VE)O(VE)。虽然SPFA算法是Bellman-Ford算法的优化,但是对于一些特殊的图可能因为有判断操作和出队入队操作导致两者复杂度相近。
Bellman-Ford算法和SPFA算法相关推荐
- Bellman算法和SPFA算法
Dijkstra算法比较快速,但是如果遇到负边就无能为力了,而Bellman算法可以解决负边问题,只要不是负环. 这个算法数据结构没有讲过,他主要是每次对所以边进行松弛操作,进行n-1次得到最短路径. ...
- 【最短路径】:Dijkstra算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法
求最短路径最常用的算法有: Dijkstra算法.SPFA算法.Bellman-Ford算法和Floyd-Warshall算法. Dijkstra算法.SPFA算法.Bellman-Ford算法这三个 ...
- BF算法和KMP算法
给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式.这里将介绍处理串匹配问题的两种算法,BF算法和KMP算法. BF算法 (暴力匹配 ...
- Algorithm:C++语言实现之字符串相关算法(字符串的循环左移、字符串的全排列、带有同个字符的全排列、串匹配问题的BF算法和KMP算法)
Algorithm:C++语言实现之字符串相关算法(字符串的循环左移.字符串的全排列.带有同个字符的全排列.串匹配问题的BF算法和KMP算法) 目录 一.字符串的算法 1.字符串的循环左移 2.字符串 ...
- 操作系统之存储管理——FIFO算法和LRU算法
操作系统之进程调度--优先权法和轮转法(附上样例讲解) 操作系统之银行家算法-详解流程及案例数据 操作系统之多线程编程-读者优先/写者优先详解 操作系统之存储管理--FIFO算法和LRU算法 操作系统 ...
- 若S作主串,P作模式串,试分别写出利用BF算法和KMP算法的匹配过程。
目 录 题目: 百度文库-答案: (1) (2) MOOC标准答案: (1) (2) mooc答案-截图: 数据结构(C语言版)-严蔚敏2007 题目: 设字符串S='aabaabaabaac', ...
- C++实现bellman ford贝尔曼-福特算法(最短路径)(附完整源码)
C++实现bellman ford贝尔曼-福特算法 实现bellman ford贝尔曼-福特算法的完整源码(定义,实现,main函数测试) 实现bellman ford贝尔曼-福特算法的完整源码(定义 ...
- Prim算法和Kruskal算法
Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...
- 基于Huffman算法和LZ77算法的文件压缩的改进方向
基于Huffman算法和LZ77算法的文件压缩(八) 到这里已经简单实现基于Huffman算法和LZ77算法的文件压缩, GitHub源码:点我 根据基于Huffman算法和LZ77算法的文件压缩(七 ...
最新文章
- android TextView实现滚动显示效果
- Redis 的性能幻想与残酷现实(转)
- 利用webpack和vue实现组件化
- 来总结一下在VC中调用COM组件的方法
- opcuaclient 文档_连接协议-OPC UA Client
- go int 转切片_「快学 Go 语言」第 4 课——低调的数组
- com.android.tools.build:gradle:2.3.3,关于com.android.tools.build:gradle:3.4.2的构建问题
- python expect模块_Python尚学堂高淇|第二季0408P119P123with上常见的异常的解决tryexcept...else结构,...
- 如何安装mysql5.7.2_CentOS 7.2 安装MySQL 5.7
- 20145226夏艺华 《Java程序设计》预备作业3
- 一个兼容IE7\IE8,H5的多功能视频播放器,H5视频播放器兼容Flash视频播放器
- 怎么修改远程服务器的地址,怎么修改远程服务器的地址
- 原生的文件上傳和下载
- 为什么 12306 时不时要崩那么一下?
- 美封锁对华半导体出口:14nm制造可以 X86设计不行
- 把Unity的jdk环境添加到环境变量
- python语法学习第二天--条件与循环
- Python+Django开发游戏充值管理后台
- Flutter-Ink家族
- 计算机房灭火器单具基准,厂房、车间灭火器配置计算范例
热门文章
- Python 字典 values() 方法
- 004-JQuery属性
- Error0---local variable S is accessed from within inner class; needs to be declared final
- HTML5笔记——formData
- IOS开发之Swift学习笔记
- QT mainwindow四件套
- poj3335 半平面交
- spring对事务的控制 AOP
- java resultset 映射到实例_[Java]ResultSet的用法与实例
- 一个div压在另一个div上面_【CSS小分享】用CSS画一个新拟态风格键盘