演算法筆記---最短路路徑之Floyd(弗洛伊德)演算法
阿新 • • 發佈:2019-01-25
最短路路徑之Floyd(弗洛伊德)演算法
Floyd-Warshall演算法(Floyd-Warshall algorithm)是解決任意兩點間的最短路徑的一種演算法,可以正確處理有向圖或負權的最短路徑問題。
Floyd-Warshall演算法的時間複雜度為O(N3),空間複雜度為O(N2)。
[編輯]原理
Floyd-Warshall演算法的原理是動態規劃。
設Di,j,k為從i到j的只以(1..k)集合中的節點為中間節點的最短路徑的長度。
- 若最短路徑經過點k,則D
- 若最短路徑不經過點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; }