总结分析
- 是一个简单的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;
}