题目链接:传送门
无向图最小环,floyed来求
普通的松弛操作还是有,就是
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示从
i
i
i到
j
j
j的最短路
题目要求一个最小的环,存下一开始边的大小
d
[
i
]
[
j
]
d[i][j]
d[i][j]
用中转点
k
,
d
[
i
]
[
j
]
,
f
[
i
]
[
j
]
k,d[i][j],f[i][j]
k,d[i][j],f[i][j]来更新答案,
d
[
i
]
[
k
]
+
d
[
k
]
[
j
]
+
f
[
i
]
[
j
]
d[i][k]+d[k][j]+f[i][j]
d[i][k]+d[k][j]+f[i][j]就是这个最小的环,因为
f
[
i
]
[
j
]
f[i][j]
f[i][j]求出的最小的路径不经过
k
k
k
题目还要求输出路径,再用一个数组记录每个点的后面节点,要跟着
f
f
f一起更新,再一个
v
e
c
t
o
r
vector
vector记录路径即可
#include <bits/stdc++.h>
#define A 110
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f / 2;
int n, m, a, b, c, d[A][A], f[A][A], ans = inf, nxt[A][A];
vector<int> v;
int main(int argc, char const *argv[]) {
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
d[i][j] = f[i][j] = inf;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
d[a][b] = d[b][a] = f[a][b] = f[b][a] = min(d[a][b], c);
nxt[a][b] = b; nxt[b][a] = a;
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (ans > d[i][k] + d[k][j] + f[i][j]) {
ans = d[i][k] + d[k][j] + f[i][j];
v.clear();
for (int fr = i; fr != j; fr = nxt[fr][j]) v.push_back(fr);
v.push_back(j); v.push_back(k);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j and j != k and f[i][j] > f[i][k] + f[k][j])
f[i][j] = f[i][k] + f[k][j], nxt[i][j] = nxt[i][k];
}
if (ans == inf) puts("No solution.");
else for (auto i : v) cout << i << " ";
}