Floyd求最短路
查看題干,可以發現數據有以下特點,這也說明了folyd算法適用條件。
圖中可能存在重邊和自環,邊權可能為負數。數據保證圖中不存在負權回路。
一、代碼模板
void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
}
1.1首先介紹為什么把k放最外層
測試數據如下:x,y,z代表着x點->y點 距離= 1
1 10 4 //點1到點10距離為4
10 9 2
9 7 3
...
假設1-7的最短路徑為:1-10-9-7
d[1][9] = d[1][10] + d[10][7] = d[1][9]+d[9][7]
如果我們把k放最里,會發現當我們要求1-7的最小距離的時候,只能遍歷
1-1-7,1-2-7,1-3-7,... ,1-n-7
會發現我們還沒有遍歷1-k-10,1-k-9,而當我們遍歷到1-k-9(或1-k-10)的時候我們又沒法更新1-7的距離,
1.2 我們再來介紹一下為什么可以處理負邊
floyd可以處理負邊的原因很簡單,因為我們是采用暴力枚舉的方法,每個邊僅算一次,但是當產生負權回路的時候就出問題了。
1.3 當處理負權回路的時候產生的問題
測試數據如下:
1 2 -5
2 3 -3
3 1 -6
會發現1-3的距離變成了-22。
那么這個結果是怎么出現的呢?
1-k-3的結果產生來自三個地方:
1-1-3
1-2-3
1-3-3
拿1-3-3舉例發現:1-3來自於1-2-3 = -8
3-3來自於3-1-3=INF,3-2-3=-14,當然當k=3,i=1,j=3還沒有遍歷到3-3-3
所以最短為-14-8=-22
二、floyd的應用
- 求最短路徑
- 傳遞閉包
- 找最小環
- 恰好經過k條邊的最短路(倍增)