天天看點

7-16 最短路徑算法(Floyd-Warshall)

在帶權有向圖G中,求G中的任意一對頂點間的最短路徑問題,也是十分常見的一種問題。

解決這個問題的一個方法是執行n次迪傑斯特拉算法,這樣就可以求出每一對頂點間的最短路徑,執行的時間複雜度為O(n3)。

而另一種算法是由弗洛伊德提出的,時間複雜度同樣是O(n3),但算法的形式簡單很多。

在本題中,讀入一個有向圖的帶權鄰接矩陣(即數組表示),建立有向圖并使用Floyd算法求出每一對頂點間的最短路徑長度。

輸入格式:

輸入的第一行包含1個正整數n,表示圖中共有n個頂點。其中n不超過50。

以後的n行中每行有n個用空格隔開的整數。對于第i行的第j個整數,如果大于0,則表示第i個頂點有指向第j個頂點的有向邊,且權值為對應的整數值;如果這個整數為0,則表示沒有i指向j的有向邊。

當i和j相等的時候,保證對應的整數為0。

輸出格式:

共有n行,每行有n個整數,表示源點至每一個頂點的最短路徑長度。

如果不存在從源點至相應頂點的路徑,輸出-1。對于某個頂點到其本身的最短路徑長度,輸出0。

請在每個整數後輸出一個空格,并請注意行尾輸出換行。

輸入樣例:

4
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
           

輸出樣例:

0 3 2 1 
6 0 4 7 
2 5 0 3 
3 6 1 0 
           

代碼長度限制

16 KB

時間限制

400 ms

記憶體限制

64 MB

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 55;
int n;
int d[N][N];

void floyd()
{
    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> d[i][j];
            if (d[i][j] == 0) d[i][j] = inf;
        }
    }
    floyd();
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (i == j) cout << "0 ";
            else if (d[i][j] == inf) cout << "-1 ";
            else cout << d[i][j] << " ";
        }
        cout << endl;
    }
}
           

繼續閱讀