• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
观光之旅 Floyd-求最小环

观光之旅 Floyd 求最小环

题目

观光之旅途

思路

​ 设路径\(u_i \rightarrow u_w \rightarrow u_j \rightarrow \dots \rightarrow u_i\) 表示环\(S\), 其中\(w\)表示路径中编号最大的点,且\(i\)和\(j\) 是直接连接\(w\)点,那么任意的环都可以表示为\(C(i, w, j)\).

​ 我们假定\(d(i, j)\)为\(u_i \rightarrow \dots \rightarrow u_j\)的最短路径且只经过编号为\([1, w)\)点,\(v(i, j)\) 为\(i\)和\(j\)的直接边权,那么所有环的最小权值可以表示成为\(d(i, j) + v(i, w) + v(w, j)\)。

​ 利用上述性质,我们可以使用\(Floyd\)算法,在\(Floyd\)算法中\(d(i, j)\)表示了经过编号为\([1, w)\)内的点的最小边权,因此我们可以在算法中每次枚举\(w\)来求最小环。另外求最小环的路径的时候,应该在\(Floyd\)算法中求,因为只经过\([1, w)\)内的点。

Code

#include <bits/stdc++.h>

using i64 = long long;

int n, m, ans, ti, tj, tm;

int g[110][110], val[110][110];

int p[110][110];

std::vector<int> res;

void path(int i, int j) {
	if (!p[i][j]) return;
	int k = p[i][j];
	path(i, k);
	// std::cout << k << " ";
	res.push_back(k);
	path(k, j);
}

void floyd() {
	ans = 0x3f3f3f3f;

	memcpy(val, g, sizeof g);

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

		for (int i = 1; i < k; i ++) {
			for (int j = 1; j < i; j ++) {
				// ans = std::min(ans, g[i][j] + val[i][k] + val[k][j]);
				if (ans > g[i][j] + val[i][k] + val[k][j]) {
					ti = i, tj = j, tm = k;
					
					ans = g[i][j] + val[i][k] + val[k][j];

					res.clear();
					res.push_back(i);
					res.push_back(k);
					res.push_back(j);					
					path(j, i);					
				}		
			}
		}

		for (int i = 1; i <= n; i ++) {
			for (int j = 1; j <= n; j ++) {
				// g[i][j] = std::min(g[i][j], g[i][k] + g[k][j]);
				if (g[i][j] > g[i][k] + g[k][j]) {
					g[i][j] = g[i][k] + g[k][j];	
					p[i][j] = k;
				}
			}
		}
		
	}
}

 
int main() {
	std::cin >> n >> m;

	for (int i = 1; i <= n; i ++) {
		for (int j = 1; j <= n; j ++) {
			g[i][j] = (i == j)?0:0x3f3f3f3f;
		}
	}

	while (m --) {
		int a, b, c;

		std::cin >> a >> b >> c;

		g[a][b] = g[b][a] = std::min(c, g[a][b]);
	}

	floyd();

	if (ans == 0x3f3f3f3f) {
		return puts("No solution."), 0;
	}

	for (int i = 0; i < res.size(); i ++) {
		std::cout << res[i] << " \n"[i == (int) res.size() - 1];
	}
}
posted on 2023-05-04 20:06  Jack404  阅读(18)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3