1. 程式人生 > 實用技巧 >Floyd演算法

Floyd演算法

多源最短路問題

給定一張 \(n\) 個點的有向圖,要求出任意兩點間的最短路。

\(\text{Floyd}\) 演算法

簡介

這是一個基於動態規劃思想的最短路演算法。

它可以求出所有點對間的最短路。

時間複雜度為 \(O(n^3)\)

演算法流程

\(dis[k][i][j]\) 表示從 \(i\)\(j\) ,只經過 \(1,2,...,k\) 的最短路長度。

故有 \(dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]),1≤i,j,k≤n\)

注意:在進行迴圈時要先列舉 \(k\)

於是我們有如下的程式碼:

for(Re int k=1;k<=n;k++)
{
    for(Re int i=1;i<=n;i++)
    {
        for(Re int j=1;j<=n;j++)
        {
            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        }
    }
}

應用

1. 給一個正權無向圖,找一個權值和最小的環。

首先我們知道這一定是個簡單環。

於是考慮這個環是怎麼構成的。

設環上編號最大的結點 \(u\)

\(f[u-1][x][y]\)\((u,x)\) , \((u,y)\) 共同構成了環。

故在 \(\text{Floyd}\) 的過程中列舉 \(u\) ,計算這個和的最小值即可。

2. 給定一個有向圖,已知其中任意兩點之間是否有連邊,要求判斷任意兩點的連通性。

這就是所謂圖的傳遞閉包問題。

我們只需要按照 \(\text{Floyd}\) 的過程,逐個加入點判斷一下。

只是此時的取 \(\min\) 變成了位運算( 或運算和與運算 )。

for(Re int k=1;k<=n;k++)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            f[i][j]|=f[i][k]&f[k][j];
        }
    }
}