第25章《所有节点对的最短路径》: Floyd-Warshall算法,python实现

最短路径

本节讨论有向图 G = ( V , E ) G=(V,E) G=(V,E)上所有节点对最短路径问题的一种动态规划算法。
对于图 G = ( V , E ) G=(V,E) G=(V,E)的所有节点对最短路径问题,一条最短路径的所有子路径都是最短路径。

Floyd-Warshall算法

我们使用一种不同的动态规划公式来解决所有节点对最短路径问题。所产生的算法称为Floyd-Warshall算法。Floyd-Warshall算法对带权重的无向图和有向图都起作用,但是图中不能有环中各边权重之和为负数的环路。
假设有一个graph图如下:
在这里插入图片描述
接下来步骤Floyd-Warshall算法找到图中所有节点paris对的最短路径。

Step 1: 创建一个n*n的矩阵 A 0 A^0 A0

其中 n n n是节点数量,第 i i i行和第 j j j列分别代表节点 i i i j j j,矩阵 A A A中的每个单元 A [ i ] [ j ] A[i][j] A[i][j]代表第 i i i个节点到第 j j j个节点的距离。如果两个节点之间没有路径,则值为无穷大。
所以对于上面的graph图,我们有得到如下路径矩阵:
A 0 = [ 0 3 ∞ 5 2 0 ∞ 4 ∞ 1 0 ∞ ∞ ∞ 2 0 ] A^0 = \begin{bmatrix} 0 & 3 & \infty & 5 \\ 2 & 0 & \infty & 4 \\ \infty & 1 & 0 & \infty \\ \infty & \infty & 2 & 0 \end{bmatrix} A0=0230102540

Step 2:用矩阵 A 0 A^0 A0创建 A 1 A^1 A1

假如 k k k是从原节点到目标节点的最短路径的中间节点,如果 A [ i ] [ j ] > A [ i ] [ k ] + A [ k ] [ j ] A[i][j] > A[i][k] + A[k][j] A[i][j]>A[i][k]+A[k][j],则用最新的路径距离更新 A [ i ] [ j ] A[i][j] A[i][j],重新更新最短路径过程中,每次第 k k k列和第 k k k行值保持不变
A 1 = [ 0 3 ∞ 5 2 0 ∞ 0 ∞ 0 ] − − > [ 0 3 ∞ 5 2 0 9 4 ∞ 1 0 8 ∞ ∞ 2 0 ] A^1 = \begin{bmatrix} 0 & 3 & \infty & 5 \\ 2 & 0 \\ \infty & &0 \\ \infty & &&0 \end{bmatrix} --> \begin{bmatrix} 0 & 3 & \infty & 5 \\ 2 & 0 & 9 & 4 \\ \infty & 1&0 & 8 \\ \infty & \infty &2&0 \end{bmatrix} A1=0230050>023019025480

Step 3:用矩阵 A 1 A^1 A1创建 A 2 A^2 A2

A 2 = [ 0 3 2 0 9 4 1 0 ∞ 0 ] − − > [ 0 3 9 5 2 0 9 4 3 1 0 5 ∞ ∞ 2 0 ] A^2 = \begin{bmatrix} 0 & 3 \\ 2 & 0 & 9 & 4\\ & 1&0 \\ &\infty &&0 \end{bmatrix} --> \begin{bmatrix} 0 & 3 &9 & 5 \\ 2 & 0 & 9 & 4 \\3 & 1&0 & 5 \\ \infty & \infty &2&0 \end{bmatrix} A2=023019040>02330199025450

Step 4:用矩阵 A 2 A^2 A2创建 A 3 A^3 A3

A 3 = [ 0 ∞ 0 9 ∞ 1 0 8 2 0 ] − − > [ 0 3 9 5 2 0 9 4 3 1 0 5 5 3 2 0 ] A^3= \begin{bmatrix} 0 & &\infty \\ & 0 & 9 & \\ \infty &1&0 &8\\ &&2&0 \end{bmatrix} --> \begin{bmatrix} 0 & 3 &9 & 5 \\ 2 & 0 & 9 & 4 \\3 & 1&0 & 5 \\ 5 & 3 &2&0 \end{bmatrix} A3=00190280>0235301399025450

Step 5:用矩阵 A 3 A^3 A3创建 A 4 A^4 A4

A 4 = [ 0 5 0 4 0 5 5 3 2 0 ] − − > [ 0 3 7 5 2 0 6 4 3 1 0 5 5 3 2 0 ] A^4= \begin{bmatrix} 0 & &&5 \\ & 0 & &4 \\ &&0 &5\\ 5&3&2&0 \end{bmatrix} --> \begin{bmatrix} 0 & 3 &7 & 5 \\ 2 & 0 & 6 & 4 \\3 & 1&0 & 5 \\ 5 & 3 &2&0 \end{bmatrix} A4=0503025450>0235301376025450

A 4 A^4 A4给定了每两个节点之间的最短距离。

python实现如下:

# -*-coding:utf8 -*-

import sys


INF= float("inf")

class Graph:
	def __init__(self, vertices, graph):
		self.vertices = vertices
		self.graph = graph
		self.distance = list(map(lambda i: list(map(lambda j:j,i)), self.graph))

	def floyd_warshall(self):
		for k in range(self.vertices):
			for i in range(self.vertices):
				for j in range(self.vertices):
					self.distance[i][j] = min(self.distance[i][j], self.distance[i][k]+self.distance[k][j])
	
	def show_result(self):
		for i in range(self.vertices):
			for j in range(self.vertices):
				if (self.distance[i][j] == INF):
					print("INF", end=" ")
				else:
					print(self.distance[i][j], end="  ")
			print(" ")


if __name__=='__main__':
	G = [[0, 3, INF, 5],
		 [2, 0, INF, 4],
		 [INF, 1, 0, INF],
		 [INF, INF, 2, 0]]
	verticies = 4
	example = Graph(verticies, G)
	example.floyd_warshall()
	example.show_result()

猜你喜欢

转载自blog.csdn.net/BGoodHabit/article/details/107504124