最短路径算法 | Bellman-Ford Algorithm

这篇具有很好参考价值的文章主要介绍了最短路径算法 | Bellman-Ford Algorithm。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我们在之前的文章中已经讨论了最短路径算法中最经典的Dijkstra‘s Algorithm。然而,Dijkstra's Algorithm虽然好用,却仍然存在一些缺点即无法解决带有负权重路线的问题,改进后的Dijkstra算法尽管可以解决一些简单的负权重问题,但仍然无法解决带有负循环的图的最短路径问题。

为了弥补Dijkstra's Algorithm的缺点,我们需要借用一个适用于任何图的最短路径算法,那就是我们今天要介绍的贝尔曼-福德算法。

Dijkstra 算法是一种贪心算法,时间复杂度为 O((V+E)LogV)(使用优先序列改进后)。Dijkstra 不适用于具有负权重的图,Bellman-Ford 适用于此类图,同时Bellman-Ford 也比 Dijkstra 更容易实现,并且非常适合分布式系统,缺点是 Bellman-Ford 的时间复杂度是 O(V * E) 

使用 Bellman-Ford Algorithm 查找到所有顶点的最短距离的步骤:

  • 首先,初始化从源点到所有顶点的距离为无穷,原点到原点本身的距离为 0,即创建大小为 |V| 的数组 dist[] 所有值都是无限的,除了 dist[src] ,其中 src 是源顶点。
  • 然后,计算最短路径,下面的操作重复执行 |V|-1 次,这里 |V| 是给定图中的顶点数,每次对每个边缘 uv 执行以下操作 
    • 如果 dist[v] > dist[u] + 边 uv 的权重,则更新 dist[v] 为dist[v] = dist[u] + 边 uv 的权重
  • 最后检查图中是否存在负权重循环。再次遍历每条边,对每条边uv执行以下操作:
    • 如果dist[v] > dist[u] + 边uv的权重,那么“图包含负权重循环” 
    • 第三步的思路是,第二步求出最短路径(如果图表不包含负权重循环)。如果我们再次遍历所有边并发现任何顶点存在更短的路径,则证明存在负权重循环。

Bellman-Ford Algorithm 的原理

与其他动态规划问题一样,该算法以自下而上的方式计算最短路径。它首先计算路径中最多有一条边的最短距离。然后,它计算最多有 2 条边的最短路径,依此类推。在外循环的第 i 次迭代之后,计算最多具有 i 条边的最短路径。可以有最大值 |V| – 任何简单路径中的 1 条边,这就是外循环运行 |v| 的原因 – 1 次。这个想法是,假设如果我们计算了最多具有 i 个边的最短路径,则没有负权重循环,那么对所有边的迭代保证给出最多具有 (i+1) 个边的最短路径。

算法图解

第 1 步:设0为起点。将所有距离初始化为无穷,除了0到自身的距离。图中的顶点总数为 5,因此每条边都必须处理 4 次。

最短路径算法 | Bellman-Ford Algorithm

第二步:所有边按如下顺序处理:(B, E), (D, B), (B, D), (A, B), (A, C), (D, C), ( B, C), (E, D)。当第一次处理所有边时,我们得到以下距离。第一行显示初始距离。第二行显示处理边缘 (B, E)、(D, B)、(B, D) 和 (A, B) 时的距离。第三行显示处理(A,C)时的距离。第四行显示处理 (D, C)、(B, C) 和 (E, D)时的距离。 

最短路径算法 | Bellman-Ford Algorithm

 第 3 步:第一次迭代计算出了最短路径只包涵一条边的距离。第二次遍历所有边时,我们得到以下距离(最后一行显示最终值)。

最短路径算法 | Bellman-Ford Algorithm

第 4 步:第二次遍历保证给出最多 2 条边的所有最短路径。注意,第二次遍历后所有距离已经最小化,因此第三次和第四次遍历不会更新距离。 

下面是Bellman-Ford算法的Python实现

class Graph:

	def __init__(self, vertices):
		self.V = vertices # No. of vertices
		self.graph = []

	# function to add an edge to graph
	def addEdge(self, u, v, w):
		self.graph.append([u, v, w])

	# utility function used to print the solution
	def printArr(self, dist):
		print("Vertex Distance from Source")
		for i in range(self.V):
			print("{0}\t\t{1}".format(i, dist[i]))

	# The main function that finds shortest distances from src to
	# all other vertices using Bellman-Ford algorithm. The function
	# also detects negative weight cycle
	def BellmanFord(self, src):

		# Step 1: Initialize distances from src to all other vertices
		# as INFINITE
		dist = [float("Inf")] * self.V
		dist[src] = 0

		# Step 2: Relax all edges |V| - 1 times. A simple shortest
		# path from src to any other vertex can have at-most |V| - 1
		# edges
		for _ in range(self.V - 1):
			# Update dist value and parent index of the adjacent vertices of
			# the picked vertex. Consider only those vertices which are still in
			# queue
			for u, v, w in self.graph:
				if dist[u] != float("Inf") and dist[u] + w < dist[v]:
					dist[v] = dist[u] + w

		# Step 3: check for negative-weight cycles. The above step
		# guarantees shortest distances if graph doesn't contain
		# negative weight cycle. If we get a shorter path, then there
		# is a cycle.

		for u, v, w in self.graph:
			if dist[u] != float("Inf") and dist[u] + w < dist[v]:
				print("Graph contains negative weight cycle")
				return

		# print all distance
		self.printArr(dist)


# Driver's code
if __name__ == '__main__':
	g = Graph(5)
	g.addEdge(0, 1, -1)
	g.addEdge(0, 2, 4)
	g.addEdge(1, 2, 3)
	g.addEdge(1, 3, 2)
	g.addEdge(1, 4, 2)
	g.addEdge(3, 2, 5)
	g.addEdge(3, 1, 1)
	g.addEdge(4, 3, -3)

	# function call
	g.BellmanFord(0)


 其他语言实现下载链接:

(包含各种语言:C、Python、Java、C++、C#、Javascript等均有示例)

免费​资源下载:Bellman-Ford Algorithm文章来源地址https://www.toymoban.com/news/detail-478004.html

到了这里,关于最短路径算法 | Bellman-Ford Algorithm的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Bellman-Ford-贝尔曼-福特-算法求最短路-负环

    Bellman-Ford(贝尔曼-福特)算法基于松弛操作的单源最短路算法。 e[u]存u点的出边的邻点和边权,d[u]存u点到源点的距离。 初始化,ds]=0,d[其它点]=+o; 执行多轮循环。每轮循环,对所有边都尝试进行一次松弛操作; 当一轮循环中没有成功的松弛操作时,算法停止 为什么最坏需要

    2024年02月13日
    浏览(27)
  • 【算法基础:搜索与图论】3.4 求最短路算法(Dijkstra&bellman-ford&spfa&Floyd)

    关于最短路可见:https://oi-wiki.org/graph/shortest-path/ 无向图 是一种 特殊的 有向图。(所以上面的知识地图上没有区分边有向还是无向) 关于存储:稠密图用邻接矩阵,稀疏图用邻接表。 朴素Dijkstra 和 堆优化Dijkstra算法的 选择就在于图 是 稠密的还是稀疏的。 算法步骤: 有一

    2024年02月16日
    浏览(33)
  • 最短路问题 Bellman-Ford(单源最短路径)(图解)

    对于边(u,v),用dist(u)和(u,v)的和尝试更新dist(v):                          dist(v) = min(dist(v) , dist(u)+l(u,v) 注:dist(i)为源点(起点)到i点的距离,l(u,v)为u-v的边权。 Bellman-Ford的基本操作是进行多次迭代,每一轮迭代对图上所有边进行松弛操作,直到

    2024年02月09日
    浏览(28)
  • 单源最短路径(spfa,Dijkstra, bellman-ford)

    目录  Dijkstra 原理:基于贪心。 为什么 Dijkstra 不能处理有负边的情况 Bellman-ford 原理:动态规划, 实质见floyd的另一篇博客 1,能找负环, 2,有变数限制的最短路径 spfa 原理 spfa怎么求负环, 原理:基于贪心。 第一步 初始化距离,dist[1] = 0, 一号点到起点的距离为0, 其他点

    2024年02月04日
    浏览(40)
  • 图论 - 最短路(Dijkstra、Bellman-Ford、SPFA、Floyd)

    单源:在边权正数时,稠密图用朴素Dijkstra,稀疏图用堆优化Dijkstra;存在负权边时,一般用SPFA,但是如果限制在k步内,则用Bellman-Ford。多源:只有Floyd,这个由于时间复杂度太高,在算法比赛中很少遇见。 1.问题描述 给定一个 n 个点 m 条边的有向图,图中可能存在重边和自

    2024年04月14日
    浏览(29)
  • Bellman-ford 贝尔曼-福特算法

    Bellman-ford算法可以解决负权图的单源最短路径问题 --- 它的优点是可以解决有负权边的单源最短路径问题, 而且可以判断是否负权回路 它也有明显的缺点,它的时间复杂度O(N*E)(N是点数 , E是边数)普遍是要高于Dijkstra算法O(N^2)的,像这里,我们使用邻接矩阵实现,那

    2024年02月06日
    浏览(30)
  • 图搜索算法详解 - DFS、BFS、Bellman-Ford、Dijkstra

    图搜索算法是许多应用程序的基础,例如社交网络分析、路径规划、数据挖掘和推荐系统。在本文中,我们将深入探讨图搜索算法的世界,探索它们的定义、重要性和实际应用。 图搜索算法是一种用于遍历图的技术,图是由 关系 连接的 节点集合 。在社交网络、网页或生物

    2024年02月16日
    浏览(32)
  • 算法基础复盘笔记Day06【搜索与图论】—— Dijkstra、bellman-ford、spfa、Floyd

    ❤ 作者主页:欢迎来到我的技术博客😎 ❀ 个人介绍:大家好,本人热衷于 Java后端开发 ,欢迎来交流学习哦!( ̄▽ ̄)~* 🍊 如果文章对您有帮助,记得 关注 、 点赞 、 收藏 、 评论 ⭐️⭐️⭐️ 📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉 1. 题目

    2023年04月22日
    浏览(35)
  • 图论详解——Bellman-Ford(清晰易懂)

    开学第一周,晚上属实作业有点乱 于是就拖更了一周 今天我们来讲解一下图论最短路径算法中 最简单 最清晰易懂 同时时间复杂度最高的算法 它的时间复杂度能达到O(VE)(点的数量*边的数量) 在学习Bellman-Ford之前,你需要先学会链式前向星 大家可以上网或者其他途径自行

    2024年02月06日
    浏览(31)
  • C++ | 数据结构与算法 | 单源最短路径 | Dijkstra && Bellman Ford

    (关于代码实现的图结构,可以看图结构的实现这篇文章) Dijkstra的实现与Prim的实现相似,两者都是通过贪心思想实现,它们有什么不同呢?首先Prim算法是针对无向图的最小生成树的,而Dijkstra算法是针对 有向图 的最短路径生成。一个的目的是连接图中的所有顶点,生成一

    2024年02月03日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包