總結分析
- 是一個簡單的dp
- 像迪傑斯特拉算法,不斷對兩個結點之間的距離進行松弛
- 松弛:比如原本記錄結點1到結點4的距離為6,這次k是結點2,結點1到結點2距離為2,結點2到結點4的距離為3,總距離為5,即可更新結點1到結點4的距離
- 還不是很懂dp,所以不太會解釋
- 結點k是結點i和j之間的中轉站
注意
- 時間復雜度O(n³)
- 多源最短路徑,其實可以對每個結點使用一次dijstra算法,也是(n³),只是使用floyd算法代碼長度短很多且易於理解
- 可以解決負權圖,不能解決負環圖
- 為什么d[i][k]是最小的:因為假設有k1<k,我們會有d[i][k]=min(d[i][k],d[i][k1]+d[k1][k]),輪到d[i][k]就說明之前已經確定它是最小的了
題目
求每一個頂點之間的最短路徑
代碼
#include <iostream>
#include <vector>
#include <iomanip>
#include <algorithm>
using namespace std;
#define n 7
#define inf 233
vector<vector<int>> G(n, vector<int>(n, inf));
void floyd() {
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
}
}
}
}
int main() {
G[0][2] = 2;
G[0][1] = 5;
G[1][3] = 1;
G[1][4] = 6;
G[1][0] = 5;
G[2][3] = 6;
G[2][5] = 8;
G[2][0] = 2;
G[3][2] = 6;
G[3][1] = 1;
G[3][4] = 1;
G[3][5] = 2;
G[4][1] = 6;
G[4][3] = 1;
G[4][6] = 7;
G[5][2] = 8;
G[5][3] = 2;
G[5][6] = 3;
G[6][4] = 7;
G[6][5] = 3;
//對角線為0
for (int i = 0; i < n; i++) G[i][i] = 0;
for (auto a : G) {
for (auto b : a) {
//如果是inf233,改為輸出-1
if (b == 233) cout << setw(2) << -1 << " ";
else cout << setw(2) << b << " ";
}
cout << endl;
}
floyd();
cout << endl << "完成floyd算法后" << endl;
for (auto a : G) {
for (auto b : a) {
cout << setw(2) << b << " ";
}
cout << endl;
}
return 0;
}