当前位置: 首页 > news >正文

【算法】Bellman-Ford单源最短路径算法(附动图)

目录

一、性质

二、思路

三、有边路限制的最短路


一、性质

  • 适用于含有负权边的图(Dijkstra不适用)

  • 更简单,但效率慢

  • 如果对应路径存在负权回路则没有最短路径(可用于判断图中是否存在负权回路)

  • 相比于spfa,若最短路径有边数限制则只能使用Bellman-Ford

负权回路:图中带环且环中所有边的权重和为负


二、思路

Bellman-Ford算法的思路十分简单粗暴

与Dijkstra类似的,我们用一个dist数组存放源节点到任意节点的最短路径

首先,在求最短路径前,我们需要将源节点到自己的距离初始化为0,到其他节点的距离初始化为最大值

然后,我们遍历所有的边

对于一条边,我们这里可以直接用一个结构体存储其信息,例如:

struct edge{int a, b, w;
}edges[M];

其中a为有向边出发的节点,b为有向边指向的节点,w为边的权重

遍历所有的边,如果 dist[a]+w < dist[b] ,则更新最短路径

以同样的方式一共循环n次,我们就能得到源节点到任意节点的最短路径

 

有时不一定非要循环n次才能得到最优解,例如上面我们只循环了3次。但最坏的情况下,如果我们的图是这样的呢?

有n个节点,但只有n-1条边,我们至少循环n-1次才能将所有节点更新

那我们不能只循环n-1次吗?

前面提到,Bellman-Ford算法可用于检测图中是否存在负权回路,具体是如何检测的?靠的就是这多出来的一次循环

首先解释一下为何路径中存在负权回路则不存在最短路径,因为我们如果在这个负权回路中一直走,那么路径长度不就一直在变小直到负无穷吗?

可以看到,在上面最坏的情况下,我们也只需要循环n-1次就能将源节点到每个节点的最短路径求出来,而最后一次循环中不会有节点被更新。但如果存在负权回路,则最后一次循环中一定还会有节点被更新。通过判断我们就可以知道图中是否存在负权回路。

即使每次遍历边的顺序不同也不会影响最后的结果,但每次循环中dist数组中的值可能不同。因为如果遍历边的顺序与边的指向一致,我们可以连续更新多个节点,例如:

可以看到dist的数组更新是串联的,即一个位置更新可能影响到其他位置,如果我们没有对最短路径的边数进行限制的话就无需多虑,但如果最短路径有边数限制,那我们就需要一个额外的备份数组来辅助节点更新


三、有边路限制的最短路

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;const int N = 510, M = 10010;struct edge{int a, b, w;
}edges[M];int n, m, k;
int dist[N], backup[N]; 
//最短路径有边数限制,所以我们还需要一个备份数组int bellman_ford()
{//初始化dist数组memset(dist, 0x3f, sizeof dist); dist[1] = 0; //最短路径不能超过k条边,因此我们循环k次for(int i = 0;i < k;i++) {//将上一次循环中dist数组的结果存入backup数组memcpy(backup, dist, sizeof dist); for(int j = 0;j < m;j++){int a, b, w;a = edges[j].a, b = edges[j].b, w = edges[j].w;dist[b] = min(dist[b], backup[a] + w); //用backup数组来更新dist数组}}return dist[n];
}int main()
{cin >> n >> m >> k;for(int i = 0;i < m;i++){int a, b, w;cin >> a >> b >> w;edges[i] = {a,b,w}; //存边}int ans = bellman_ford(); //Bellman-Ford算法if(ans > 0x3f3f3f3f / 2) cout << "impossible"; //返回值过大不符合预期,可以判断不存在满足条件的路径else cout << ans;return 0;
}

如有错误,欢迎在评论区指出

完.


http://www.mrgr.cn/news/57748.html

相关文章:

  • 讲解机器学习中的 K-均值聚类算法及其优缺点。(AI)
  • Qt 实战(11)样式表 | 11.2、使用样式表
  • docker之redis安装(项目部署准备)
  • 【CVPR 2025】1 论文模板中文版详细指南:从格式到提交要求
  • Maven3.9.9环境安装配置
  • w~自动驾驶合集9
  • Orthanc局域网访问、IP访问、远程访问服务器
  • Linux的目录结构 常用基础命令(2)
  • 【网络】:网络基础
  • 解决url含%导致404错误
  • flink使用hikariCP数据库连接池,导致连接泄露
  • 【含文档】基于ssm+jsp的爱旅行平台的设计与实现(含源码+数据库+lw)
  • uboot源码makefile基础及启动流程梳理
  • 2024年必收藏!最全 禅道 项目管理软件各版本安装部署全攻略
  • 网络地址和本地网络地址
  • [ComfyUI]Flux:超赞古风少女LORA,唯美江南水乡小桥流水轻舟江南美人
  • 手写路由Vue-Router源码实现原理
  • 昇思MindSpore进阶教程--安装常见问题(下)
  • Spring Boot植物健康系统:智慧农业的新趋势
  • com.baomidou.mybatisplus.extension.service.IService用法详解及使用例子
  • 用phython处理当前路径的文件
  • 口含烟贴纸设计公司哪家好?
  • 算法复习核心题目策略总结,以便回顾
  • STM32 C语言基础知识
  • JavaWeb合集22-Apache POI
  • 某游戏的某促销活动,会向玩家推荐一个道具