floyd 算法笔记
floyd 是一个全源最短路算法,时间复杂度 \(O(n^3)\)。
时间好慢啊,但是超好写的好吗。
floyd 的本质其实就是动态规划。设 \(dis_{i,j}\) 为 \(i\to j\) 的最短路,转移方程便是寻找一个中间点 \(k\),松弛 \(i\to j\) 的路径,将其变为 \(i\to k\to j\) 的路径长度,状态转移如下:
\[dis_{i,j}=\min\{dis_{i,j},dis_{i,k}+dis_{k,j}\}
\]
\[(i,j,k\le n)
\]
由于 \(k\) 是需要松弛 \(i\to j\) 这条边的点,所以 \(k\) 必须是最外层循环。
接下来考虑边界,很明显初始所有的 \(dis_{i,j}\) 都为极大值,给出 \((u_i,v_i,w_i)\) 这条无向边时(注意是无向边)。
\[dis_{u_i,v_i}=w_i,dis_{v_i,u_i}=w_i
\]
这样初始化就完成了。
floyd 模板代码如下:
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 2e5 + 5, kInf = 1e9 + 7;
int n, m;
int dis[kMaxN][kMaxN];
void Floyd() { // dp 进行 floyd。
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
return;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
fill(dis + 1, dis + 1 + n, kInf);
cin >> n >> m;
for (int i = 1, u, v, w; i <= n; i++) {
cin >> u >> v >> w;
dis[u][v] = dis[v][u] = w;
// 若是有向边代码这么写:
// dis[u][v] = w;
}
Floyd(); // 求出最短路。
return 0;
}
例题: