Floyd–Warshall算法简介

  Floyd–Warshall算法用于寻找有向图中任意两点间的最短路径,即多源最短路径。该算法可用于带负权边的图,但不能用于带负权环的图。该算法需要比较每一组节点间所有的路径,时间复杂度为Θ(|V|^3)。

  设有一个图G,有N个节点,编号为1,2,…,N。函数shortestPath(i, j, k) 返回当仅使用点集{1,2,…,k}为中间节点时,从节点i到达节点j的最短距离。使用w(i, j)表示i和j之间边的权值,则对于节点(i, j)之间的最短路径,有两种情况:

(1)最短路径是从节点i直接到节点j,则有:

shortestPath(i, j, 0) = w(i, j)

(2)最短路径是从节点i,经过非空节点集{1, 2, …, k}中的某些点作为中间节点,到达节点j。此情况又可以根据最短路径是否经过节点k,来继续分解求以下两条路径中较短的那一条:

  • 不经过节点k时,从i到j的最短距离即为shortestPath(i, j, k – 1) ;
  • 经过节点k时,从i到j的最短距离是从i到k的最短距离加上从j到k的最短距离,即shortestPath(i, k, k) + shortestPath(k, j, k) 。

则(2)中从i到j的最短路径即为shortestPath(i, j, k – 1) 和shortestPath(i, k, k) + shortestPath(k, j, k) 中较短的那一条,即:

shortestPath(i, j, k) = min(shortestPath(i, j, k - 1), shortestPath(i, k, k) + shortestPath(k, j, k))

  由此计算shortestPath(i, j, N) ,即为任意两点(i, j)间的最短距离。Wiki给出了算法的伪代码如下:
let dist be a |V| × |V| array of minimum distances initialized to ∞ (infinity)
for each vertex v
	dist[v][v] ← 0
for each edge (u,v)
	dist[u][v] ← w(u,v)  // the weight of the edge (u,v)
for k from 1 to |V|
	for i from 1 to |V|
		for j from 1 to |V|
			if dist[i][j] > dist[i][k] + dist[k][j] 
				dist[i][j] ← dist[i][k] + dist[k][j]
			end if