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;
}

例题:

posted @ 2023-07-11 08:01  liruixiong0101  阅读(8)  评论(0编辑  收藏  举报