Fish Graph

这篇题解中也只能找出任意环。

here

每次会把环上的后继加进去,所以刚好每个点都被加入一次。

hn[1]是终点x,然后是它的第一个邻居。

调整的证明看魏老师题解,然后这个操作:

就是找到环上第一个与x直接相连的点,然后调整环为这个环。

反证容易证明这个环是极小的。

他就是按照两条红线(任意一个)的顺序,找到一个极小环。

所以其实直接dfs确实是找不到所有环的。

void dfs(int u, int from) {
	printf("%d -> %d\n", ~from ? e[from ^ 1] : -1, u);
	ins[u] = true;
	st[u] = true;
	if (~from) fa[u] = e[from ^ 1];
	for (int i = h[u]; ~i; i = ne[i]) {
		if (i == (from ^ 1)) continue ;
		int v = e[i];
		if (!st[v]) {
			dfs(v, i);
		}
		else if (ins[v]) {
			int t = u;
			while (t != v) {
				printf("%d ", t);
				t = fa[t];
			}
			printf("%d\n", v);
		}
	}
	ins[u] = false;
}
4 6
1 2
2 4
4 3
3 1
2 5
5 3

输出:

-1 -> 1
1 -> 3
3 -> 5
5 -> 2
2 -> 4
4 2 5 3
2 5 3 1

上面的方法只能判环,不能找环,枚举不到1 2 4 3这个环。

如何在线性的时间内,找出包含一个点的环呢?

不会写……


记住这样写找不到所有环就行了,本题这么写是因为有证明(见ALexwei的题解),所以找到任意环后调整即可。

回溯的时候一定会遍历这条边,不要跳过它。

这个时候就可以了,但是复杂度就抽象了,因为你可能每个环都要check一下。

一直WA的原因,一个度为4的点不一定是答案,因为它可能不在环上:


然后那个宽搜写法是错的。

走到一个访问过的点只能说明起点能走到一个环上,不能说明起点就在环上。

所以要像Alexwei那样,记录起点的邻居,然后判断是不是来自不同的邻居

而且直觉这样是可以找到最小环,至于为何最小环不会被拆开,不会证……

大概画一下吧……

之前觉得所有环都可以是从起点走,然后相遇,其实这样想是错的。

因为环上的边可能不是搜索树上的边,就走不到这个环。

比如上面深搜的样例,但是我们是可以证明宽搜走到的环一定是最小环的。

不想证……


posted @   Zlc晨鑫  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示