AcWing 344. 观光之旅 && 无向图的最小环

题目链接:传送门

无向图最小环,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 << " ";
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良月澪二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值