算法复习——图算法篇之单源最短路径之Bellman-Ford算法

算法复习——图算法篇之单源最短路径之Bellman-Ford算法

以下内容主要参考中国大学MOOC《算法设计与分析》,墙裂推荐希望入门算法的童鞋学习!

1. 问题背景

​ 在计算带权图中源点到所有其他顶点的最短路径时,如果图中存在负权边,Dijkstra算法不再适用。

​ 那么图中存在负权边时,是否存在单源最短路径?

​ 如果源点 s s s可达负环,则难以定义最短路径。因为可以绕负环,不断松弛到 − ∞ -∞

​ 若源点 s s s无可达负环,则存在源点 s s s的单源最短路径。

2. 问题定义

单源最短路径问题(Single Source Shortest Paths Problem)

输入:

  • 带权图 G = < V , E , W > G=<V, E, W> G=<V,E,W>
  • 源点编号 s s s

输出:

  • 源点 s s s到所有其他顶点 t t t的最短距离 δ ( s , t ) \delta(s, t) δ(s,t)和最短路径 < s , … , t > <s, \dots, t> <s,,t>
  • 或存在源点 s s s可达的负环

挑战1:图中存在负权边时,如何求解单源最短路径?

挑战2:图中存在负权边时,如何发现源点可达负环?

3. 算法思想

  • Dijkstra算法通过松弛操作迭代更新最短距离
  • 存在负权边时,需要比Dijkstra算法更多次数的松弛操作

问题:图中存在负权边时,如何利用松弛操作求解单源最短路?

  • Bellman-Ford算法
    • 解决挑战1:图中存在负权边时,如何求解单源最短路径?
      • 每轮对所有边进行松弛,持续迭代 ∣ V ∣ − 1 |V|-1 V1
    • 解决挑战2:图中存在负权边时,如何发现源点可达负环?
      • 若第 ∣ V ∣ |V| V轮仍松弛成功,存在源点 s s s可达的负环

4. 伪代码

Bellman-Ford(G, s)

输入:图G=<V, E, W>,源点s

输出:单源最短路径P

新建一维数组dist[1..|V|],pred[1..|V|]
// 初始化
for u ∈ V do
	dist[u] ← ∞
	pred[u] ← NULL
end
dist[s] ← 0
// 执行单源最短路径算法
for i ← 1 to |V| - 1 do
	for (u, v) ∈ E do
		if dist[u] + w(u, v) < dist[v] then
			dist[v] ← dist[u] + w(u, v)
			pred[v] ← u
		end
	end
end
for (u, v) ∈ E do
	if dist[u] + w(u, v) < dist[v] then
		print 存在负环
		break
	end
end

​ 该算法的时间复杂度是 O ( ∣ V ∣ ∗ ∣ E ∣ ) O(|V|*|E|) O(VE)

5. 算法正确性证明

  • 挑战1:图中存在负权边时,如何求解单源最短路径?
    • 解决方案:每轮对所有边进行松弛,持续迭代 ∣ V ∣ − 1 |V|-1 V1
  • 最坏情况
    • 非环路的路径 < s , v 2 , v 3 , … , v ∣ V ∣ > <s, v_2, v_3, \dots, v_{|V|}> <s,v2,v3,,vV>至多经过 ∣ V ∣ − 1 |V|-1 V1条边
    • 最坏情况下进行 ∣ V ∣ − 1 |V|-1 V1轮松弛操作,可以保证求得单源最短路径
  • 挑战2:图中存在负权边时,如何发现源点可达负环?
    • 解决方案:若第 ∣ V ∣ |V| V轮仍松弛成功,存在源点 s s s可达负环
  • 若源点 s s s可达负环,可松弛成功无限次
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值