基环树,图内找环技巧

基环树,图内找环技巧

我开始的想法是,DFS记录当前正在走的一条路径,当遇到曾经走过的点,那么就成环,然后fa往回跳记录即可。

但是我发现,没有办法记录两个点构成的环,因为我们在dfs的时候,通常会将连接父亲的点重复边,一般会 continue

,所以这就导致我们解决不了两个点的环。

找环代码

void dfs1(int u,int pre)
{
	fa[u]=pre; vis2[u]=++num;
	for (int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if (v==pre) continue;
		if (vis2[v])
		{
			if (vis2[v]<vis2[u]) continue;
			int x=v;
			while (x!=u)
			{
				st[++top]=x;
				vis[x]=1;//标记在环上 
				x=fa[x];
			}
			st[++top]=u;
			vis[u]=1;
		}
		dfs1(v,u);
	}

原理,vis2中存储的是每个点的dfs序,我们知道对于一个环,我们会在dfs时遇到两次,第一次是子节v点访问到曾祖父节点,形成环,第二次是回溯时,回溯到曾祖父节点,然后继续枚举该点连接的其他点时,枚举到子节点。对于第一次相遇,其实和我之前的想法是一样,我们普遍认为,最好想的找环就是遇到曾经遇到的,但是解决不了上述的问题。

而第二次相遇就可以很好的避免上述问题,哪怕是只有两个点的自环,v 节点也会被同样访问两次,因为建边的时候会建立两组相同的边。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值