关于Floyd-Warshall算法由前趋矩阵计算出的最短路径反映出了算法的执行过程特性的证明
引言:Floyd-Warshall算法作为经典的动态规划算法,能够在O(n3)复杂度之内计算出所有点对之间的最短路径,且由于其常数较小,对于中等规模数据运行效率依然可观。算法共使用n此迭代,n为顶点个数。其中第k次迭代计算出每对顶点之间所有中间结点小于等于k的最短路径长度,其中i到j的最短路径要么是经过k的一条路径,这条路径的由k所分割出的两个路径i → k、k → j是中间路径小于等于k-1的最短路径;要么是从i到j的中间路径小于等于k-1的最短路径。定义dij(k)为从i到j的最短路径长度,可以形式化地表示其计算方法:
(1)
算法为了得出最短路径的所有中间结点,维护前趋矩阵Π。其元素 πij 表示从i到j的最短路径上j前一结点,其计算方法如下:
(2)
(3)
从前趋矩阵得出最短路径所有结点的方法如下:
PRINT-SHORTEST-PATH (i, j, Π)
1 STACK ← Ø
2 while j ≠ i
3 PUSH (STACK, j)
4 j ← Π (i, j)
5 PUSH (STACK, j)
6 while STACK ≠ Ø
7 v ← POP (STACK)
8 print v
问题描述:关于Floyd-Warshall算法的细节请参见《算法导论》或其他算法专著,笔者在阅读《算法导论》相关章节的时候萌生了关于题目所述问题的猜想,表述如下:算法最终得出dij之前,一定在之前的某个第k次迭代对dij(k)做了使其等于dik(k-1) + dkj(k-1)的赋值,假设k为最后这一次这样的迭代,那么算法隐含了这样一个信息:最终从i到j的最短路径中间经过k,且从i到k和从k到j的中间路径小于等于k-1。而从i到k和从k到j亦符合类似的模式,这样一直递归下去,直到得到的两个点的最短路径为图中一条边。可以为所有最短路径构造一棵树表示这个过程。举例来说,对于路径3257416,其相对应的反映了算法构造路径过程的树为:
图1
那么,由PRINT-SHORTEST-PATH所得出的路径是不是就这样一条路径呢?答案竟然是肯定的。下面将会给出证明,其中,推论1的证明使用了最短路径的一些性质,而结论的证明使用的就是算法证明里最重要的递归思想和数学归纳法。
首先给出并证明一个比较重要的推论。
推论1:若在第k次迭代,某个从i到j的路径经过了k,令m = πij(k),如果m ≠ k,则从i到m的路径也经过k。
证明:由于πkj(k-1) = πij(k)= m,即,从k到j的中间结点小于等于k-1在最短路径中,j的前趋为m,所以有
dkj(k-1) = dkm(k-1) + wmj (4,最短路径的最优子结构性质)
其中wmj为边(m, j)的权值。
因为从m到j有一条边,由最短路径的三角不等式可得:
dij(k-1) ≤ dim(k-1) + wmj (反证即可得)
即
dim(k-1) ≥ dij(k-1) - wmj (5)
由条件可知
dij(k-1) > dik(k-1) + dkj(k-1)
两边减去wmj,得
dij(k-1) - wmj > dik(k-1) + dkj(k-1) - wmj = dik(k-1) + dkm(k-1) (由4)
即
dij(k-1) - wmj > dik(k-1) + dkm(k-1)
得证
结论:对由PRINT-SHORTEST-PATH所得出的路径构造一颗如图1所示的树,这颗树反映了Floyd-Warshall算法构造最短路径的过程。
证明:利用数学归纳法,显而易见,第一次迭代之前,对初始的前趋矩阵应用PRINT-SHORTEST-PATH函数得到的路径反映了算法初始时没有中间结点的最短路径的构造过程。
接下来,假设,算法对第k-1次迭代所得的前趋矩阵Πk-1,应用PRINT-SHORTEST-PATH函数得到的路径,反映了算法构造中间结点小于等于k-1的最短路径的过程。并根据这个假设,证明算法对第k次迭代所得的前趋矩阵Πk,应用PRINT-SHORTEST-PATH函数得到的路径,反映了算法构造中间结点小于等于k的最短路径的过程即可。
1. 对于某个从i到j的算法所构造出的中间结点小于等于k的最短路径,若其不经过k,有 dij(k) = dij(k-1),πij(k) = πij(k-1) = m,对其应用PRINT-SHORTEST-PATH函数可得序列:
πij(k) = m
πim(k) = n
...
πio(k) = p
πip(k) = i
对于其中任意一个 πix(k),其一定等于πix(k-1),即从i到这条路径中任意一个x的最短路径都不会经过k,否则就会与假设矛盾。因此有:
πij(k) = πij(k-1) = m
πim(k) = πim(k-1) = n
...
πio(k) = πio(k-1) = p
πip(k) = πip(k-1) = i
即根据Πk所计算出来的从i到j的路径等同于根据Πk-1所计算出来的从i到j的路径。由于根据Πk-1所计算出来的路径是符合性质的中间结点小于等于k-1的路径,因此根据Πk,对任意不经过k的最短路径应用PRINT-SHORTEST-PATH函数计算出的路径即是符合性质的中间结点小于等于k的路径。
2. 若从i到j的路径经过k,即
dij(k) = dik(k-1) + dkj(k-1),πij(k) = πkj(k-1)= m
由推论1可得,根据Πk,对从i到j的最短路径应用PRINT-SHORTEST-PATH函数计算出的路径一定会到达k,且有:
πij(k) = πkj(k-1) = m
πim(k) = πkm(k-1) = n
...
πio(k) = πko(k-1) = p
πip(k) = πkp(k-1) = k
这个从k到j的序列的所有点都来自Πk-1,所以它是符合性质的中间结点小于等于k-1的路径。
而对于从i到k的序列,由于其不经过k,因此根据1,也是符合性质的中间结点小于等于k-1的路径。
由于路径从k一分为二且k为所有中间结点中最大的那个,所以这条路径符合所构造的树先从最大的中间结点分开的性质。而分开的两条路径又分别是符合性质的中间结点小于等于k-1的路径,因此第k迭代构造的经过k的路径是符合性质的中间结点小于等于k的路径。
综上所述,可以得出结论
____________________________
本博客文章主要供博主学习交流用,所有描述、代码无法保证准确性,如有问题可以留言共同讨论。