点双连通分量/圆方树

点双连通分量

定义

点双连通分量的定义有很多种,比如:“图中任意两不同点之间都有至少两条点不重复的路径。”,“不存在割点的图。”,一般采用前者,这是最初的定义。

两个定义的区别在于一种特殊情况:图中只有两个点和一条把两点连接起来的边。

除此之外,两者是等价的。

模板

模板题

好像没找到以前写的代码,于是鸽了,有需求可以上网搜索。(这题我用的圆方树。)

性质

对于一个点双中的两点,它们之间简单路径的并集,恰好完全等于这个点双。

即同一个点双中的两不同点 \(u,v\) 之间一定存在一条简单路径经过给定的在同一个点双内的另一点 \(w\)

圆方树

定义

可以看PinkRabbit的博客

这里不再赘述。

构造

其实就是每找到一个点双就加入一个方点把这个点双的所有点串起来。

具体可以见代码。

代码

如果我们想判断一个点是圆点还是方点,只需要判断其编号是否大于 \(n\) 即可。

int dfn[N],low[N],DFN,tp,sta[N];
void tarjan(int x){
	dfn[x]=low[x]=++DFN;sta[++tp]=x;
	for(register int i=head[x];i;i=nex[i]){
		int y=to[i];
		if(!dfn[y]){
			tarjan(y);low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]){
				cnt++;
				for(int u=0;u!=y;tp--) u=sta[tp],add(cnt,u),add(u,cnt);
				add(cnt,x),add(x,cnt);
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
	return ;
}
cnt=n;
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i),tp--;

性质

两圆点在圆方树上的路径,与路径上经过的方点相邻的圆点的集合,就等于原图中两点简单路径上的点集。
(证明见PinkRabbit的博客

圆方树上不是叶子的圆点都是原图的割点。

两点间必经点等价于圆方树上两点路径上的所有圆点组成的集合。

posted @ 2021-09-24 21:01  __Anchor  阅读(105)  评论(0)    收藏  举报