Fish Graph
这篇题解中也只能找出任意环。
每次会把环上的后继加进去,所以刚好每个点都被加入一次。
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那样,记录起点的邻居,然后判断是不是来自不同的邻居。
而且直觉这样是可以找到最小环,至于为何最小环不会被拆开,不会证……
大概画一下吧……
之前觉得所有环都可以是从起点走,然后相遇,其实这样想是错的。
因为环上的边可能不是搜索树上的边,就走不到这个环。
比如上面深搜的样例,但是我们是可以证明宽搜走到的环一定是最小环的。
不想证……
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】