所有结点对的最短路径问题(All-Paris Shortest Paths)

《算法导论》所有结点对的最短路径问题学习笔记

我们已经讨论了单源最短路径问题,在这篇博客中我们将求解一个图中所有节点之间的最短路径。

一、最短路径和矩阵乘法

分析可知在一个图中一条最短路径的所有子路径都是最短路径,很容易想到我们可以使用动态规划的思路来解决这个问题。

所有结点对的最短路径问题(All-Paris Shortest Paths)为从i到j的一条最短路径,且这条路径最多包含m条边。我们可以得到以下的递推公式:

所有结点对的最短路径问题(All-Paris Shortest Paths)

依据上面的递推公式我们可以编写代码如***意这里实现的是已知所有结点对的最短路径问题(All-Paris Shortest Paths)和输入的权重矩阵W推算所有结点对的最短路径问题(All-Paris Shortest Paths)

所有结点对的最短路径问题(All-Paris Shortest Paths)

观察上面的代码,如果你使用代码实现过矩阵乘法就会发现两者的相似之处,下面给出矩阵乘法的伪代码便于读者比较。

所有结点对的最短路径问题(All-Paris Shortest Paths)

接下来我们利用EXTENTED-SHORTEST_PATHS来定义一种新的矩阵运算,我们可以得到以下的矩阵序列。

所有结点对的最短路径问题(All-Paris Shortest Paths)

直接迭代进行“乘法”运算是不明智的,我们引入了一种方法来改进算法。

所有结点对的最短路径问题(All-Paris Shortest Paths)

这样我们可以减少进行矩阵乘法运算的次数,应对大规模的矩阵乘法运算非常有效。引入了这个方法后我们的时间复杂度为所有结点对的最短路径问题(All-Paris Shortest Paths)

二、Floyd-Warshall算法

在这里我们使用一种不同的动态规划公式来解决所有结点对最短路径的问题,其运行时间为所有结点对的最短路径问题(All-Paris Shortest Paths)

首先我们定义中间结点的概念。简单路径所有结点对的最短路径问题(All-Paris Shortest Paths)上的中间结点指的是路径p上除所有结点对的最短路径问题(All-Paris Shortest Paths)所有结点对的最短路径问题(All-Paris Shortest Paths)以外的任意结点,也就是处于集合所有结点对的最短路径问题(All-Paris Shortest Paths)中的结点。

假定图G的所有节点为V={1,2,3...,n},考虑其中的一个子集{1,2,3...,k},这里k是某个小于n的正数。考虑从结点i到结点j所有中间结点均取自集合{1,2,3..,k}的路径,并设p为其中权重最小的路径(路径p是简单路径),则问题可以分解成下面两种情况。

1. 如果k不是路径p上的中间结点,则路径p上所有中间结点都属于集合{1,2,3,...,k-1}。这时结点i到结点j的一条最短路径的中间结点取自于{1,2,3...,k-1}也等效于取自{1,2,3,...,k}的说法。

2. 如果结点k是路径p上的中间结点,则我们可以将路径p分解成所有结点对的最短路径问题(All-Paris Shortest Paths),则可以推出所有结点对的最短路径问题(All-Paris Shortest Paths)所有结点对的最短路径问题(All-Paris Shortest Paths)上所有中间结点都属于集合所有结点对的最短路径问题(All-Paris Shortest Paths)

基于上面的讨论我们可以归纳出一个递推公式:

所有结点对的最短路径问题(All-Paris Shortest Paths)

这个时候我们再次使用自底向上的方法来求解递归式。

所有结点对的最短路径问题(All-Paris Shortest Paths)

观察代码的形式,我们发现我们可以再次使用矩阵运算来解决这个问题了。