首页 > 其他分享 >知识点整理——最小环

知识点整理——最小环

时间:2023-03-02 12:12:23浏览次数:47  
标签:知识点 int auto tt 最小 dfs 整理 dis

前言

近日刷图论题遇到了多道求解最小环的例题,由于方法众多,用法不尽相同,数次被此所困扰。在互联网上寻找良久,却没能发现什么系统性的整理,所以便有了此文。

求解此类问题:

给出一张图,输出图中最小环的大小。定义最小环为:由 \(k(k \ge 3)\) 个点构成的最小的简单环。

标准写法1:\(\tt flody\)

应用极为广泛的做法,本质是求出最短路后暴力枚举。泛用性高、代码短,唯一的缺点是时间复杂度较高,为 \(\mathcal O(N^3)\) 。

有向图 无向图
有边权
无边权

模板:

int flody(int n) {
	for (int i = 1; i <= n; ++ i) {
		for (int j = 1; j <= n; ++ j) {
			val[i][j] = dis[i][j]; // 记录最初的边权值
		}
	}
	int ans = 0x3f3f3f3f;
	for (int k = 1; k <= n; ++ k) {
		for (int i = 1; i < k; ++ i) { // 注意这里是没有等于号的
			for (int j = 1; j < i; ++ j) {
				ans = min(ans, dis[i][j] + val[i][k] + val[k][j]);
			}
		}
	for (int i = 1; i <= n; ++ i) { // 往下是标准的flody
		for (int j = 1; j <= n; ++ j) {
			dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
			}
		}
	}
	return ans;
}

有限制的写法:\(\tt bfs\)

本质也是求解最短路,只适用于无边权图。复杂度 \(\mathcal O(N^2)\) 。

有向图 无向图
有边权
无边权
int solve(int n) {
	auto bfs = [&] (int s) {
		queue<int> q; q.push(s);
		dis[s] = 0;
		fa[s] = -1;
		while (q.size()) {
			auto x = q.front(); q.pop();
			for (auto y : ver[x]) {
				if (y == fa[x]) continue;
				if (dis[y] == -1) {
					dis[y] = dis[x] + 1;
					fa[y] = x;
					q.push(y);
				}
				else ans = min(ans, dis[x] + dis[y] + 1);
			}
		}
	};
	for (int i = 1; i <= n; ++ i) {
		fill(dis + 1, dis + 1 + n, -1);
		bfs(i);
	}
	return cout << ans;
}

对比算法:\(\tt dfs\)

一句话概括该种写法:能够输出图中其中一个简单环的大小,而不是最小环。本方法在本质上是使用了 \(\tt dfs\) 序加以处理,与 \(\tt tarjan\) 相仿。

时间仓促,直接引用做题时的截图为例,在下图中,最小环为 \(2-6-5-2\) ,而使用 \(\tt dfs\) 会输出 \(2-3-4-5-6-2\) 这个简单环。

截图

虽然这个做法不能找到最小环,但是由于其优秀的复杂度,在某些题目的解题过程中是必不可少的。

function<void(int, int)> dfs = [&] (int x, int f) {
	for (auto y : ver[x]) {
		if (y == f) continue;
		if (dis[y] == -1) {
			dis[y] = dis[x] + 1;
			fa[y] = x;
			dfs(y, x);
		}
		else if (dis[y] < dis[x] && dis[x] - dis[y] <= k - 1) { // 遇到了更小的时间戳
			cout << dis[x] - dis[y] + 1 << endl; // 输出简单环的大小
			int pre = x;
			cout << pre << " "; // 输出环上元素
			while (pre != y) {
				pre = fa[pre];
				cout << pre << " ";
			}
			exit(0);
		}
	}
};
dis[1] = 0;
dfs(1, -1);

标签:知识点,int,auto,tt,最小,dfs,整理,dis
From: https://www.cnblogs.com/WIDA/p/17171346.html

相关文章