首页 > 其他分享 >学习笔记——双连通分量

学习笔记——双连通分量

时间:2022-11-13 10:12:02浏览次数:54  
标签:连通 int Tarjan 笔记 bcc dfn low 割点 分量

前言

我们的神,MC 曾经曰过,Tarjan 是 \(11\) 级算法。

边双

桥: 在一张连通无向图中,如果去掉一条边使得图的极大连通分量增加了,那么这条边就叫做桥。
边双连通分量: 一张无向图中的一个极大连通子图不存在桥,那么这个子图就是边双(e-bcc)。

性质: 一张无向图进行边双缩点之后是一棵树。

求桥

直接记录 dfnlow,意义和 Tarjan 缩点相同。但是不用记录栈。遍历儿子的时候判断是否有 low[s]>dfn[x],如果是,说明儿子无法到达当前节点的祖先,也就是当前边是桥。对边记录编号后打标记即可。

void Tarjan(int x,int fa){
	dfn[x]=low[x]=++tot;
	for(pii s:g[x]){
		if(s.fi==fa) continue;
		if(!dfn[s.fi]){
			Tarjan(s.fi,x);
			low[x]=min(low[x],low[s.fi]);
			if(dfn[x]<low[s.fi]) vis[s.se]=vis[s.se^1]=1;
		}else low[x]=min(low[x],dfn[s.fi]);
	}
}

求 e-bcc

方法一: 用上面的方法求出所有的桥,然后去掉桥后每一个极大连通图就是一个 e-bcc。

void dfs(int x){
	col[x]=bcc;
	for(pii s:g[x]){
		if(vis[s.se]) continue;
		if(col[s.fi]) continue;
		dfs(s.fi);
	}
}

方法二: 也可以用 Tarjan 直接求 e-bcc。同样记录一个栈,在同一个 e-bcc 的点仍然会在一起。然后和普通的缩点没有很大区别。注意需要处理重边,因为两个点之间如果有重边,这两个点也属于同一个 e-bcc。我们直接在做的时候记录父亲,然后看儿子中父亲出现了几次,第一次出现的时候 continue,之后再出现说明是重边。

void Tarjan(int x,int fa){
	dfn[x]=low[x]=++tot;stk[++top]=x;
	bool flag=0;
	for(int s:g[x]){
		if(s==fa&&!flag){flag=1;continue;}
		if(!dfn[s]) Tarjan(s,x),low[x]=min(low[x],low[s]);
		else if(!col[s]) low[x]=min(low[x],dfn[s]);
	}if(dfn[x]==low[x]){
		bcc++;do{
			col[stk[top]]=bcc;
		}while(stk[top--]!=x);
	}
}

点双

割点: 在一张无向图中,去掉一个点和这个点所连接的边,极大连通分量增加,那么这个点是割点。
点双连通分量: 无向图中的一个极大连通子图,如果它没有割点,那么它就是一个点双连通分量(p-bcc)。

性质: 割点会同属于两个 p-bcc,所以在题目中我们一般采用圆方树来把点双问题转化为树上问题。

求割点

同样维护 dfnlow,如果 dfn[x]<=low[s],说明 \(s\) 不能跨越 \(x\) 到前面的点去,则 \(x\) 是一个割点。

需要注意,对于根节点而言,没有办法用这种方式判断它是否是割点,但是我们可以看它为根的 dfs 生成树上有几条相连的树枝边,如果有 \(2\) 条以上与它相连的树枝边,那么根就是一个割点。

void Tarjan(int x,int fa){
	dfn[x]=low[x]=++tot;
	int cnt=0;
	for(int s:e[x]){
		if(!dfn[s]){
			cnt++;Tarjan(s,x);
			low[x]=min(low[x],low[s]);
			if(x!=fa&&low[s]>=dfn[x])
				ans[x]=1;
		}else if(s!=fa)
			low[x]=min(low[x],dfn[s]);
	}if(x==fa&&cnt>=2)
		ans[x]=1;
}

求 p-bcc

我们注意到一个割点属于两个不同的 p-bcc,所以用删去点后求连通图的方法行不通,所以只能采用 Tarjan 来做。

其实也很简单,只要在求割点的时候,维护一个栈就行了。

void Tarjan(int x,int fa){
	dfn[x]=low[x]=++tot;
	stk[++top]=x;
	for(int s:e[x]){
		if(!dfn[s]){
			Tarjan(s,x);
			low[x]=min(low[x],low[s]);
			if(low[s]>=dfn[x]){
				cnt++;
				while(stk[top]!=s)
					bcc[cnt].push_back(stk[top--]);
				bcc[cnt].push_back(stk[top--]);
				bcc[cnt].push_back(x);
			}
		}else low[x]=min(low[x],dfn[s]);
	}
}

简单感性理解一下为什么不需要特判根。首先如果根是割点,那么肯定是最后一个点一个 p-bcc。否则它应当会在某一个儿子的时候,从那个割点开始弹栈,然后直到弹到根。

维护 vector 是方便建树和其它操作。

后记

我们的神,MC 曾经曰过 Tarjan,是 \(11\) 级算法。
真的是 \(11\) 级吗,确定不用更高一点?

标签:连通,int,Tarjan,笔记,bcc,dfn,low,割点,分量
From: https://www.cnblogs.com/ZCETHAN/p/16885461.html

相关文章

  • Linux学习笔记(11)——进程管理与SELinux初探
    进程管理与SELinux初探进程管理与SELinux初探一、什么是进程1.1进程与程序(process&program)二、任务管理(jobcontrol)2.1什么是任务管理2.2jobcontrol的......
  • 详解主成分分析PCA与奇异值分解SVD-降维的实现方法【菜菜的sklearn课堂笔记】
    视频作者:菜菜TsaiTsai链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili二维特征矩阵降维输入原数据,结构为$(3,2)$,即三个样本,每个样本两......
  • 学习笔记-java代码审计-xxe
    java代码审计-xxe0x00漏洞挖掘java解析xml的方法有多种,比较常见的有四种:DOM、DOM4J、JDOM和SAX。//1.DocumentBuilder原生、可回显importjavax.xml.parsers.Docum......
  • 学习笔记-java代码审计-xss
    java代码审计-xss0x01漏洞挖掘protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{respon......
  • 学习笔记-java代码审计-sqli
    Java代码审计-sqli0x01漏洞挖掘jdbc在上古时期,人们往往这么从数据库获取数据。publicUsergetUserById(Stringid)throwsSQLException{Connectionconnectio......
  • 学习笔记-java代码审计-ssrf
    java代码审计-ssrf0x01漏洞挖掘java发送http请求的方式还是比较多的,下面是原生的:Stringurl=request.getParameter("url");URLu=newURL(url);//1.URL,直接打开......
  • 学习笔记-java代码审计-ssti
    java代码审计-ssti0x01漏洞挖掘Velocity@RequestMapping("/ssti/velocity")publicStringvelocity(@RequestParam(name="content")Stringcontent){Velocity......
  • 学习笔记-java代码审计-命令执行
    java代码审计-命令执行0x01漏洞挖掘Stringcmd=request.getParameter("cmd");Runtimeruntime=Runtime.getRuntime();//Runtime.getRuntime.execProcessBuilder......
  • 学习笔记-java代码审计-文件操作
    java代码审计-文件操作0x01文件上传这段代码来自菜鸟教程:privatestaticfinalStringUPLOAD_PATH="/tmp/upload";privatebooleanuploadWithFileUpload(HttpServ......
  • 学习笔记-java代码审计-反序列化
    Java代码审计-反序列化0x00漏洞挖掘业务代码简单来说,找readObject/readUnshared就好了protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresp......