AcWing 344. 观光之旅(floyd求最小环)

原题
开始口胡:
用类似dp的方法,对图中所有环进行分类
分类标准是环中编号最大的点
for(int k=1;k<=n;k++)
由floyd的原理可知当floyd的第一重循环执行到K时(还没开始执行K),所有路径都是进过1到k-1号点所形成的最短距离
当进行到K时,枚举i和j,在之前的计算中包含i,j的环的距离是d[i][j]+d[j][i],先插入K点,使式子变成w[i][k]+w[k][j]+d[j][i]取两者最小值,当把所有i,j枚举完,就能求出第K类环的最小值

#include <bits/stdc++.h>

using namespace std;
const int N = 110, INF = 1e8;
int n, m;

int d[N][N], g[N][N];
int p[N][N];//每个点是由哪个点转移过来的
int path[N], cnt; //当前环的方案 点的数量

void get_path(int i, int j) {
	if (p[i][j] == 0)
		return;
	int k = p[i][j];
	get_path(i, k); //从i走到k
	path[cnt++] = k;
	get_path(k, j); //从k走到j


}

void solve() {
	cin >> n >> m;
	int res = INF;
	memset(g, 0x3f, sizeof g);
	for (int i = 1; i <= n; i++)
		g[i][i] = 0;
	while (m--) {
		int a, b, c;
		cin >> a >> b >> c;
		g[a][b] = g[b][a] = min(c, g[a][b]);
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			d[i][j] = g[i][j];
		}
	}

	for (int k = 1; k <= n; k++) {

		for (int i = 1; i < k; i++) { //求最大环
			for (int j = i + 1; j < k; j++) {
				if ((long long)d[i][j] + g[j][k] + g[k][i] < res) {
					res = d[i][j] + g[j][k] + g[k][i];
					cnt = 0;
					path[cnt++] = k;
					path[cnt++] = i;
					get_path(i, j);
					path[cnt++] = j;
				}
			}
		}

		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if (d[i][j] > d[i][k] + d[k][j]) {
					d[i][j] = d[i][k] + d[k][j];
					p[i][j] = k; //转移的中间点
				}
			}
		}
	}
	if (res == INF) {
		cout << "No solution." << endl;
	} else {
		for (int i = 0; i < cnt; i++) {
			cout << path[i] << " ";
		}
		cout << endl;
	}

}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	solve();

}
上一篇:js md5加密完整代码


下一篇:div从上到下展现 隐藏