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;
}
相关推荐
信奥卷王7 小时前
[GESP202609 六级] 分树规划
算法
夏幻灵8 小时前
LeetCode 21:合并两个有序链表——双指针与哑节点详解
算法·leetcode·链表
徐小黑ACG9 小时前
Golang 基础05 结构体struct
开发语言·算法·golang
Navigator_Z10 小时前
LeetCode //C - 1286. Iterator for Combination
c语言·算法·leetcode
北极有牛10 小时前
cpp学习笔记--常量指针
java·开发语言·算法
GPU实战笔记10 小时前
云端 GPU 训练的账户余额提醒:它能说明什么,不能说明什么?
深度学习·算法·成本管理·gpu云计算·云端训练
浮链序10 小时前
怎么证明"你这个模型是偷我的"——把蒸馏变成取证工具
算法·安全·llm
小O的算法实验室11 小时前
IEEE TMC,面向异构物联网的多目标量子行为拓扑优化算法
算法
liliangcsdn11 小时前
派息率指标的应用探索和分析
大数据·算法