Bellman-Ford算法

对于Dijkstra算法,不妨给出这样一个例子

graph LR
A((A)) -->|1| C((C))
A -->|2|D((D))
D -->|-4| C

根据Dijkstra算法的流程,选取A为源点。更新与A邻接的顶点,有C和D。选取已更新顶点中距离A的最小值,显然选择边权为1的边所连接的顶点C,并将C收入最短路集合S中,此时已经确定A->C的最短路为1。那么问题就出现了。

由于已经收入S中的顶点都视为最短路上的顶点且不可更改,因此由Dijkstra算法确定的A->C的最短路就是1。但是显然实际的最短路是A->D->C,花销为-2。

这时我们就需要使用别的方法来求出其最短路。比如Bellman-Ford以及其使用队列优化后的SPFA

Bellman-Ford的实现

Bellman-Ford算法实际上采用动态规划的思想。首先大前提是一个结论,对于有n个顶点的图,从源点到达其他任意顶点最多经过n-1条边。

定义\(dp[i][j]\),代表最多经过\(i\)条边到达顶点\(j\)的最小花销

显然\(dp[0][j] = +\infty\)

对于给定\(dp[i][j]\),考虑其最小花销,两个方面。

  1. 考虑从前一个顶点 k 到达顶点 j ,\(dp[i][j] = dp[i-1][k] + w[k->j]\)
  2. 考虑不经过新的中间顶点(即维持原状) ,\(dp[i][j] = dp[i - 1][k]\)

状态转移方程为\(dp[i][j] = min(dp[i - 1][j] , dp[i - 1][k] + w[k ->j])\)

显然在状态转移时,更新本层的状态只用到了上一层的状态,不妨加一个滚动数组优化,使用一维数组即可。

最终的代码如下

配合例题853. 有边数限制的最短路 - AcWing题库

#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 20;
int n, m, k;
struct Edge
{
int v;
int u;
int w;
}edges[N];
int dist[N],last[N];
void bellman_ford()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for (int i = 0; i < k; i++)//这里k的含义就是经过不超过k条边的最短路
{
memcpy(last, dist, N); //last保存上一层的状态。
for (auto x : edges)
{
dist[x.v] = min(dist[x.v], last[x.u] + x.w);//更新使用上一层的状态来更新
}
}
}
int main()
{
cin >> n >> m >> k;
for (int i = 0; i < m; i++)
{
int v, u, w;
cin >> v >> u >> w;
edges[i] = { v,u,w };
}
bellman_ford();
if (dist[n] > 0x3f3f3f3f / 2)
puts("impossible");
else
cout << dist[n];
return 0;
}

这里使用last数组记录上一层的状态。可以看出,当要求求出最多经过k条边的最短路时,只可以使用bellman-ford来做。同时由于动态规划更新状态不需要有序,因此可以简化图,只存储边

使用Bellman-Ford判断负值圈

所谓负值圈就是一个权值和为负数的环,如下

flowchart LR
A((A)) -->|2| B((B))
B -->|-5| C((C))
C -->|1| A

-5 + 2 + 1 = -2,这就形成了一个负环。

存在负值圈的图一定无最短路

但是使用Bellman-Ford算法可以检测出图中是否有负值圈。

使用一个数组cnt[N]维护更新到第N个节点所经过的边数。由于从源点到达其他任意顶点最多经过n-1条边,但是对于有负值圈的图,由于总是会有更小的路径,因此其经过的边数会大于n。我们仅需要检测在某次更新中cnt[i]是否会大于n-1即可

Bellman-Ford算法实现带有负权边的单源最短路的更多相关文章

  1. poj3259 bellman——ford Wormholes解绝负权问题

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 35103   Accepted: 12805 Descr ...

  2. 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法

    Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...

  3. 单源最短路——Bellman-Ford算法

    1.Dijkstra的局限性 Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的. 列如以 ...

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

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

  5. Bellman—Ford算法思想

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

  6. 单源最短路:Dijkstra算法 及 关于负权的讨论

    描述: 对于图(有向无向都适用),求某一点到其他任一点的最短路径(不能有负权边). 操作: 1. 初始化: 一个节点大小的数组dist[n] 源点的距离初始化为0,与源点直接相连的初始化为其权重,其他 ...

  7. 模板C++ 03图论算法 1最短路之单源最短路(SPFA)

    3.1最短路之单源最短路(SPFA) 松弛:常听人说松弛,一直不懂,后来明白其实就是更新某点到源点最短距离. 邻接表:表示与一个点联通的所有路. 如果从一个点沿着某条路径出发,又回到了自己,而且所经过 ...

  8. 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)

    关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...

  9. 2018/1/28 每日一学 单源最短路的SPFA算法以及其他三大最短路算法比较总结

    刚刚AC的pj普及组第四题就是一种单源最短路. 我们知道当一个图存在负权边时像Dijkstra等算法便无法实现: 而Bellman-Ford算法的复杂度又过高O(V*E),SPFA算法便派上用场了. ...

  10. 【算法】单源最短路——Dijkstra

    对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...

随机推荐

  1. 入门篇-其之七-Java运算符(下)

    一.三元运算符的使用 三元运算符(也称作三目运算符),使用:和?表示,其格式为:布尔表达式 ? 表达式1 : 表达式2 如果布尔表达式的计算结果是true,那么执行表达式1:否则,如果布尔表达式的计算 ...

  2. window对象的常见事件

    2.1 窗口加载事件 window.onload = function() { } 或者 window.addEventListener("load", function(){}) ...

  3. java使用递归及迭代方式实现前序遍历 中序遍历 后序遍历 以及实现层序遍历

    本文为博主原创,转载请注明出处: 目录: 一.快速理解前序,中序,后序遍历的区别 二.使用递归的方式实现前序,中序,后序遍历 三. 使用迭代的方式实现前序 中序 后序遍历 四.层序遍历 一.快速理解前 ...

  4. 【RTOS】基于RTOS的嵌入式系统看门狗策略

    RTOS - high integrity systems 看门狗策略 Watchdog Strategies for RTOS enabled embedded systems 介绍 看门狗定时器就 ...

  5. JVM内存参数的学习之三

    JVM内存参数的学习之三 背景 研究启动性能时, 顺便看到了jmap -heap 1 的部分信息 看到: MinHeapFreeRatio.MaxHeapFreeRatio 自己突然以为是 Perce ...

  6. Redis不同版本,内存分配,硬件的性能研究

    Redis不同版本,内存分配,硬件的性能研究 前言 Konw more ! Do more ! Gain more ! 骨折之后开始减肥. 前段时间跳绳导致膝盖不舒服,现在改骑车和走路. 在有限的没人 ...

  7. [转帖]充分利用 Oracle SQL监控

    https://zhuanlan.zhihu.com/p/397834311 经常被问到查看执行计划的最佳工具是什么,对我来说,答案总是SQL Monitor(包含在 Oracle Tuning Pa ...

  8. [转帖]从SSTable到LSM-Tree之二

    https://zhuanlan.zhihu.com/p/103968892 背景 LSM-Tree (Log Structured Merge Tree),日志结构合并树.它在 1996 年由论文& ...

  9. 【转帖】python 安装whl文件

    前言 WHL文件是以Wheel格式保存的Python安装包,Wheel是Python发行版的标准内置包格式.在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的p ...

  10. [转帖]人脸特征计算速度优化-SIMD技术Neon介绍

    人脸特征计算速度优化-SIMD技术Neon介绍 JasonZhu 游走于秃头和研究的边缘 ​关注   15 人赞同了该文章 ​ 目录 收起 1. baseline计算 2. simd和数据重排加速 数 ...