如果询问次数过大,每次询问都进行一次dijkstra算法求最短路,时间复杂度将会非常高,所有考虑Floyd算法,Floyd特点就是可以同时求解所有点之间的最短路。
最短路3
#include <bits/stdc++.h>
using namespace std;
int n, m, q;
int f[301][301];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> q;
memset(f, 127, sizeof(f));
for (int i = 1; i <= n; i++) {
f[i][i] = 0;
}
for (int i = 1; i <= m; i++) {
int x, y, z;
cin >> x >> y >> z;
f[x][y] = z;
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (f[i][k] < 1 << 30 && f[k][j] < 1 << 30) {
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
}
}
while (q--) {
int x, y;
cin >> x >> y;
if (f[x][y] < 1 << 30) {
cout << f[x][y] << '\n';
} else {
cout << "-1" << '\n';
}
}
}
变式:删点游戏
tag:考虑逆向做,变删点为加点,加点正好是Floyd的特点之一
#include <bits/stdc++.h>
using namespace std;
int n;
int f[301][301], c[301];
bool b[301];
int a[301];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
memset(b, 0, sizeof(b));
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> f[i][j];
}
}
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
for (int l = n; l; l--) {
int k = c[l];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
b[k] = 1;
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (b[i] && b[j]) {
ans += f[i][j];
}
}
}
a[l] = ans;
}
for (int i = 1; i <= n; i++) {
cout << a[i] << " \n"[i == n];
}
}