1. 程式人生 > >演算法筆記---最短路路徑之Floyd(弗洛伊德)演算法

演算法筆記---最短路路徑之Floyd(弗洛伊德)演算法

                                                                     最短路路徑之Floyd(弗洛伊德)演算法

Floyd-Warshall演算法(Floyd-Warshall algorithm)是解決任意兩點間的最短路徑的一種演算法,可以正確處理有向圖或負權的最短路徑問題。

Floyd-Warshall演算法的時間複雜度O(N3)空間複雜度O(N2)

[編輯]原理

Floyd-Warshall演算法的原理是動態規劃

Di,j,k為從ij的只以(1..k)集合中的節點為中間節點的最短路徑的長度。

  1. 若最短路徑經過點k,則D
    i,j,k = Di,k,k − 1 + Dk,j,k − 1
  2. 若最短路徑不經過點k,則Di,j,k = Di,j,k − 1

因此,Di,j,k = min(Di,k,k − 1 + Dk,j,k − 1,Di,j,k − 1)


在實際演算法中,為了節約空間,可以直接在原來空間上進行迭代,這樣空間可降至二維。(見下面的演算法描述)

此演算法最重要的一點就是k視為中間變數:

if(map[i][k]!=inf && map[k][j]!=inf && map[i][j]>map[i][k]+map[k][j])
                    map[i][j]=map[i][k]+map[k][j];//演算法實現的關鍵所在

下面依然以HDU-OJ-1874為例子講解此題。

題目的意思不在贅述。

程式碼實現過程如下:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define inf 9999999
#define N 205
using namespace std;

int map[N][N];
int n,m,s,e;

void Flord()
{
    int i,j,k;
    for(k=0; k<n; k++)
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                if(map[i][k]!=inf && map[k][j]!=inf && map[i][j]>map[i][k]+map[k][j])
                    map[i][j]=map[i][k]+map[k][j];//演算法實現的關鍵所在
    if(map[s][e]!=inf)
        printf("%d\n",map[s][e]);
    else
        printf("-1\n");
}
int main()
{
    int i,j;
    int x,y,z;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                map[i][j]=inf;
            }
            map[i][i]=0;
        }
        for(i=0; i<m; i++)
        {
            scanf("%d %d %d",&x,&y,&z);
            if(map[x][y]>z)
                map[x][y]=map[y][x]=z;
        }
        scanf("%d %d",&s,&e);
        Flord();
    }
    return 0;
}