Bellman-Ford算法实现带有负权边的单源最短路
Bellman-Ford算法
对于Dijkstra算法,不妨给出这样一个例子
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]\),考虑其最小花销,两个方面。
- 考虑从前一个顶点 k 到达顶点 j ,\(dp[i][j] = dp[i-1][k] + w[k->j]\)
- 考虑不经过新的中间顶点(即维持原状) ,\(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判断负值圈
所谓负值圈就是一个权值和为负数的环,如下
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算法实现带有负权边的单源最短路的更多相关文章
- poj3259 bellman——ford Wormholes解绝负权问题
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 35103 Accepted: 12805 Descr ...
- 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法
Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...
- 单源最短路——Bellman-Ford算法
1.Dijkstra的局限性 Dijkstra算法是处理单源最短路径的有效算法,但它局限于边的权值非负的情况,若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的. 列如以 ...
- Bellman - Ford 算法解决最短路径问题
Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力 ...
- Bellman—Ford算法思想
---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G ...
- 单源最短路:Dijkstra算法 及 关于负权的讨论
描述: 对于图(有向无向都适用),求某一点到其他任一点的最短路径(不能有负权边). 操作: 1. 初始化: 一个节点大小的数组dist[n] 源点的距离初始化为0,与源点直接相连的初始化为其权重,其他 ...
- 模板C++ 03图论算法 1最短路之单源最短路(SPFA)
3.1最短路之单源最短路(SPFA) 松弛:常听人说松弛,一直不懂,后来明白其实就是更新某点到源点最短距离. 邻接表:表示与一个点联通的所有路. 如果从一个点沿着某条路径出发,又回到了自己,而且所经过 ...
- 最短路模板(Dijkstra & Dijkstra算法+堆优化 & bellman_ford & 单源最短路SPFA)
关于几个的区别和联系:http://www.cnblogs.com/zswbky/p/5432353.html d.每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个(草儿家到 ...
- 2018/1/28 每日一学 单源最短路的SPFA算法以及其他三大最短路算法比较总结
刚刚AC的pj普及组第四题就是一种单源最短路. 我们知道当一个图存在负权边时像Dijkstra等算法便无法实现: 而Bellman-Ford算法的复杂度又过高O(V*E),SPFA算法便派上用场了. ...
- 【算法】单源最短路——Dijkstra
对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...
随机推荐
- 深度学习基础课:使用交叉熵损失函数和Softmax激活函数(下)
大家好~本课程为"深度学习基础班"的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序 线上课程资料: 本节课录像回放 加QQ群,获得 ...
- Vue中使用el-menu高亮显示问题
https://blog.csdn.net/weixin_43336525/article/details/132541500 <template> <el-menu :defaul ...
- git速查
- java项目实战-spring-基本用法01-day24
目录 1. spring 简单介绍 2. IOC/DI --控制反转--是啥 3. 实现 3. 如果 对象的 属性为引用数据类型 如何 实例化对象 4 如何用注解的方式 以少量的代码实现对象的创建于获 ...
- 每天学五分钟 Liunx 0110 | 服务篇:守护进程 systemd
有些进程会在系统上运行较长时间,如前面的 Hello World 程序运行时产生的进程.有些进程运行瞬间就结束了,如执行 ps 命令产生的进程,也有的进程会常驻在内存中,提供相应的服务,这样的进程称为 ...
- ORA-65140: 无效的通用配置文件名称
1.问题 CREATE PROFILE PM_Profile LIMIT SESSIONS_PER_USER 100 PASSWORD_LIFE_TIME 90; 在创建概要文件时,报错:ORA-65 ...
- [转帖]MySQL数据库8.0.29-8.0.31版本使用 INSTANT 算法新增字段bug
https://www.cnblogs.com/harda/p/17528512.html xxx下发MySQL数据库共性隐患排查通知,要求统一排查MySQL数据库8.0.29及以后版本使用 INST ...
- [转帖]一篇来自网络的关于“enqueue”events的简短参考
https://www.cnblogs.com/lhdz_bj/p/8716701.html 仅供自己和各位同学参考: Enqueue Type Description enq: AD - alloc ...
- [转帖]JMeter压测Redis
https://www.cnblogs.com/yjlch1016/p/14052402.html 一.Redis Data Set插件: https://jmeter-plugins.org/wik ...
- [转帖]IO多路复用的三种机制Select,Poll,Epoll
I/O多路复用(multiplexing)的本质是通过一种机制(系统内核缓冲I/O数据),让单个进程可以监视多个文件描述符,一旦某个描述符就绪(一般是读就绪或写就绪),能够通知程序进行相应的读写操作 ...