之前介绍了 Dijkstra 单源最短路算法,本文介绍 Floyd 全源最短路算法。例题: LeetCode 1334 阈值距离内邻居最少的城市。
class Solution {
public:
int findTheCity(int n, vector<vector<int>>& edges, int distanceThreshold) {
vector f(n, vector<int>(n, INT_MAX / 2));
for (auto &e: edges) {
int x = e[0], y = e[1], wt = e[2];
f[x][y] = f[y][x] = wt;
}
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
}
int ans = 0;
int min_cnt = n;
for (int i = 0; i < n; i++) {
int cnt = 0;
for (int j= 0; j < n; j++) {
if (j != i && f[i][j] <= distanceThreshold) {
cnt++;
}
}
if (cnt <= min_cnt) {
min_cnt = cnt;
ans = i;
}
}
return ans;
}
};
Floyd 算法的核心代码非常简单,就是上文的三重循环。因此时间复杂度为 \(O(n^3)\)。需要注意的是,必须在最外层循环枚举 k。
之前介绍的朴素 Dijkstra 算法的时间复杂度为 \(O(n^2)\),执行 n 次也不过 \(O(n^3)\),那么 Floyd 算法的优势是什么呢?
第一,当然是 Floyd 的代码更加简单;第二,也是最为重要的一点,Dijsktra 无法处理具有负权边的情况,而 FLoyd 可以处理负权边,但不能处理负环。