Bellman-ford算法

Bellman-ford算法

要说求最短路径可以用之前学的Dijkstra,但是Dijkstra 不能处理负权边,更不能处理负环;Bellman-Ford 可以!

在图论体系中:

  • Dijkstra:贪心、快、只能正权
  • Bellman-Ford:迭代松弛、稳、支持负权、可判负环(高级图论必备)

松弛操作

给定一条边:u → v,边权 w

松弛公式

复制代码
if(dist[v] > dist[u] + w)
	dist[v]=dist[u]+w

说明:走 u 中转到 v,比原来 v 的路径更短,更新最短路。

发现一条更近的路,就更新距离。

Bellman-Ford 不挑点、不挑边,暴力对所有边反复松弛。

判断负环

存在一个环:绕一圈总边权和为负数。

可以无限绕环,路径长度无限变小 → 没有最短路!

设图一共有 n 个点。

在无负环的图中:

任意两点的最短路径,最多经过 n-1 条边

比如 3 个点:最短路径最多 2 条边。

所以:

  • 第 1 轮松弛:更新所有「1条边」的最短路
  • 第 2 轮松弛:更新所有「2条边」的最短路
  • ......
  • 第 n-1 轮松弛:更新所有最长合法最短路

n-1 轮之后,所有点的最短路一定已经收敛,不会再更新 ,如果第 n 轮还能成功松弛,就能判断有负环

算法流程

  1. 初始化:所有点距离无穷大,起点距离为 0
  2. 迭代 n-1 轮 :每一轮遍历 所有 m 条边 做松弛
  3. 第 n 轮校验:还能松弛 = 存在负权环

时间复杂度:O(n*m)

适合:点数小、需要处理负权、判负环、差分约束问题。

Dijkstra、Bellman-ford与SPFA 的对比

整个最短路体系层级:

  • Bellman-Ford:暴力松弛、最稳、可负权、可负环、最慢
  • SPFA:队列优化版 Bellman-Ford
  • Dijkstra:贪心堆优化、只能正权、最快

Bellman-Ford 是理论基石,SPFA 是进行了队列优化。

Dijkstra 需要「遍历某个点的所有出边」,必须用邻接表/二维数组;Bellman-Ford 不需要定点遍历,它每一轮直接遍历「整张图的所有边」。

判断负环模板

三个一维数组:u[](起点)、v[](终点)、w[](边权),

复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=6005;
const int INF=0x3f3f3f3f;
int u[N],v[N],w[N],dist[N];
int n,m,cnt;
bool bellman(){
	for(int i=1;i<=n;i++){
		dist[i]=INF;
	}
	dist[1]=0;
	for(int i=1;i<n;i++){
		bool ok=false;
		for(int j=1;j<=cnt;j++){
			if(dist[u[j]]!=INF&&dist[v[j]]>dist[u[j]]+w[j]){
				dist[v[j]]=dist[u[j]]+w[j];
				ok=true;
			}
		}
		if(!ok){
			break;
		}
	}
	for(int j=1;j<=cnt;j++){
		if(dist[u[j]]!=INF&&dist[v[j]]>dist[u[j]]+w[j]){
			return true;
		}
	}
	return false;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		cnt=0;
		cin>>n>>m;
		for(int i=1;i<=m;i++){
			int a,b,c;
			cin>>a>>b>>c;
			if(c>=0){
				cnt++;
				u[cnt]=a;
				v[cnt]=b;
				w[cnt]=c;
				cnt++;
				u[cnt]=b;
				v[cnt]=a;
				w[cnt]=c;
			}
			else{
				cnt++;
				u[cnt]=a;
				v[cnt]=b;
				w[cnt]=c;
			}
		}
		if(bellman()){
			cout<<"YES"<<endl;
		}
		else{
			cout<<"NO"<<endl;
		}
	}
	return 0;
}
相关推荐
UIU11411 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场11 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi12 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David13 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院13 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng14 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
j7~16 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py17 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing18 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客18 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法