最短路径 之 Floyd 算法

• 最短路径 之 Dijkstra 算法
• 最短路径 之 Bellman 算法

Floyd算法是基于一种动态规划的思想。
点u到点v的最短路径可能是u直接到v不需要经过其他的中转点,也有可能经过两个或多个中转点后会更短 即 u -> k1 -> k2 -> ...... -> ki -> v。

当只允许经过1号顶点的时候 求最短路径 时间复杂度是 O(N²)。

for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        e[i][j] = min(e[i][j], e[i][1] + e[1][j]);

只允许经过2号顶点的时候 求最短路径 时间复杂度是 O(N²)。

for(int i = 1; i <= n; i++)
    for(int j = 1; j <= n; j++)
        e[i][j] = min(e[i][j], e[i][2] + e[2][j]);

这两个一综合就成了 只允许经过1、2号顶点时的最短路径 ,
而我们的目的是求 经过所有n个顶点时的最短路径。
所以我们只需要令k = 1, 2, 3, ..., n
就成了从i号顶点到j号顶点经过前k号顶点的最短路径,
一共进行n次便可以求得 时间复杂度是 O(N³)

for(int k = 1; k <= n; k++)
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            e[i][j] = min(e[i][j], e[i][k] + e[k][j]);

Floyd算法与顶点的关系密切,适用于稠密图,可以处理负权边,但是不能处理负权回路。
因为带有负权回路的图有可能不存在最短路径,每循环一次这个负权回路的最短路径就会减少,算法无法结束。

Floyd算法的时间复杂度为 O(N³),但由于它实现起来非常容易,所以当对时间复杂度要求不大的时候,用Floyd算法来求指定两点之间的最短路径或者指定一个点到其余各个顶点的最短路径也是可行的。

完整代码

#include 
using namespace std;
int main()
{
    int e[101][101], n, m;
    
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if(i == j)
                e[i][j] = 0;
            else
                e[i][j] = 0xffff;

    for (int i = 1; i <= m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        e[u][v] = w;
    }
    
    // Floyd - Warshall
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                e[i][j] = min(e[i][j], e[i][k] + e[k][j]);
                
    // output...
    return 0;
}

你可能感兴趣的:(最短路径 之 Floyd 算法)