上两篇博客介绍了计算单源最短路径的Bellman-Ford算法和Dijkstra算法。Bellman-Ford算法适用于任何有向图,即使图中包含负环路,它还能报告此问题。Dijkstra算法运行速度比Bellman-Ford算法要快,但是其要求图中不能包含负权重的边。
在很多实际问题中,我们需要计算图中所有结点对间的最短路径。当然,我们可以使用上述两种算法来计算每一个顶点的单源最短路径,对于图G=(V,E)来说,使用Bellman-Ford算法计算结点对最短路径的时间复杂度为O(V^2 * E),使用Dijkstra算法计算结点对最短路径的时间复杂度为O(V^3)。本文将会介绍一种应用更广泛的算法,而且它可以应用于有负权重边但没有负环路的图中,其时间复杂度为O(V^3),那就是Floyd-Warshall算法。
1. Floyd算法的原理
在上一篇博客 单源最短路径之Dijkstra算法 中,提到了图的一个重要性质:一条最短路径的子路径也是一条最短路径。因此,一条最短路径要么只包含一条直接相连的边,要么就经过一条或多条到达其它顶点的最短路径。
上图给出的是顶点i到顶点j的路径示意图。i到j的路径为<i,...,k,...,j>,其中顶点k是路径i到j的一个编号最大的中间顶点,即路径<i,...,k>中的所有顶点编号求取自集合{1,2,3,...,k-1},路径<k,...,j>也是一样的。因为