首页 > 其他分享 >圆方树

圆方树

时间:2023-08-11 16:44:43浏览次数:31  
标签:一个点 点双 圆点 路径 dfs 圆方树

构建

在将图变为树的方法里,圆方树与 v-dcc 类似。

圆方树中,原来的每个点对应一个 圆点,每个点双对应一个 方点

故圆方树的节点数为 \(n+c\),其中 \(n=|V|\),\(c=|\text{v-dcc}|\).

对于每个点双,其方点向这个点双里的每个点连边,形成一个菊花图,多个菊花图通过割点连接。

割点的数量小于 \(n\),故圆方树的点数小于 \(2n\).

若原图有 \(k\) 个连通分量显然圆方树森林有 \(k\) 颗树。


过程

Algorithm

考虑对每个连通子图构建它的圆方树。

圆方树使用的算法是 tarjan 的变体:对图 dfs,得到两个数组 \(dfn\) 和 \(low\).

  • \(dfn[u]\) 为 \(u\) 的 dfs 序。

  • \(low[u]\) 为 \(u\) 的 dfs 树的子树中的某个点 \(v\) 通过 最多一次返祖边或向父亲的树边 能访问到的 最小 dfs 序。

和割点不同的是规定了可以通过父边向上,实际上和 tarjan 的实现基本相同。


Observation

  • 每个点双在 dfs 树上是一颗连通子树,且至少包含两个点。特别地,最顶端节点仅往下接一个点。

  • 每条树边恰好在一个点双内。

考虑一个点双在 dfs 树中的最顶端节点 \(u\),那么 \(u\) 的子树包含了整个点双的信息。

再看点双的下一个点 \(v\),那么 \(u,v\) 之间存在树边。

  • 此时有 \(low[v]=dfn[u]\).

也就是,对于树边 \(u\rightarrow v\),\(u,v\) 在一个点双里,且 \(u\) 在点双中的深度最浅当且仅当 \(low[v]=dfn[u]\).

确定点双的点集用类似 tarjan 的方法即可。

在栈中被弹出的节点,将其和新建的方点连边。最后让 \(u\) 和方点连边。

code

处理有多个连通子图的情况。

int n,m,cnt;
vector<int>e[N],T[N<<1];
int dfn[N],low[N],dfc;
int st[N],top;
void tarjan(int u){
	low[u]=dfn[u]=++dfc;
	st[++top]=u;
	for(int v:e[u]){
		if(!dfn[v]){
			tarjan(v),low[u]=min(low[u],low[v]);
			if(low[v]==dfn[u]){
				cnt++;
				for(int x=0;x!=v;top--){
					x=st[top];
					T[cnt].pb(x),T[x].pb(cnt);
				}
			}
			T[cnt].pb(u),T[u].pb(cnt);
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
int main(){
	n=read(),m=read();
	cnt=n;
	for(int i=1,u,v;i<=m;i++){
		u=read(),v=read();
		e[u].pb(v),e[v].pb(u);
	}
	for(int i=1;i<=n;i++)
		if(!dfn[i])tarjan(i),top--;
	
	return 0;
}

P4630 [APIO2018] 铁人两项

一张简单无向图,问有多少三元组 \((s,c,f)\),满足 \(s\not=c\not=f\),且存在一条从 \(s\) 出发,经过 \(c\) 到达 \(f\) 的简单路径。

  • 点双中的两点之间简单路径的并集恰好完全等于这个点双。

这个性质证明比较困难。

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

然后推出另一个结论:

  • 对于两圆点在圆方树上的路径,“与路径上经过的方点相邻的圆点” 的集合等于原图中两点简单路径上的点集。

固定 \(s,f\),合法的 \(c\) 的数量等于 \(s,f\) 之间简单路径的并集的点数 \(-2\).

考虑在圆方树上计数。

在圆方树上有一个 trick:路径统计时给点赋一个合适的权值。

对方点赋值为对应点双的大小,圆点赋值为 \(-1\).

那么两圆点间路径点权和即原图中简单路径并集大小 \(-2\).

现在要对每对圆点求和。

把它变成权值 \(\times\) 经过它的路径树,简单树形 DP。

标签:一个点,点双,圆点,路径,dfs,圆方树
From: https://www.cnblogs.com/SError0819/p/17623377.html

相关文章

  • 点双边双强连通拓展(圆方树)以及一些小技巧
    点双边双强连通拓展以及一些小技巧目录点双边双强连通拓展以及一些小技巧小技巧:1.关于割点:2.关于点双和边双的判断技巧:3.关于自己制造样例的技巧:例题:拓展知识1.广义圆方树:知识点:例题:bzoj3331小技巧:1.关于割点:点双常常存在割点情况,很难搞,每次dfs都很头疼(不知道割点在哪几个连通......
  • 圆方树与仙人掌
    圆方树前置知识:点双连通分量tarjan求点双对于一个无向图,在维护某些信息时可以利用圆方树的方法把原图转为一棵树来处理我们称在原图上的点是圆点对于每个点双联通分量,新建一个连向点双内所有点的新点,称其为方点点双内的所有点除了向方点连边以外不向点双内其他点连......
  • 【题解】CF487E Tourists / 圆方树
    概念圆方树是一种基于无向图构造的树。我们知道,圆方树最早是WC上提出的处理仙人掌的东西,用于将树上做法拓展到复杂度正确的仙人掌做法。但是一些关于点双有性质的题也......
  • 从缩点到圆方树
    一些概念连通:无向图中的任意两点都可以互相到达。强连通:有向图中的任意两点都可以互相到达。连通分量:无向图的极大连通子图。强连通分量:有向图的极大强连通子图。DFS......
  • 圆方树学习笔记
    圆方树学习笔记oiwiki模板voidtarjan(intu){ dfn[u]=low[u]=++ct;st[++tp]=u;tot++; for(intv:g[u]) if(!dfn[v]) { tarjan(v);low[u]=min(low[v],low......
  • 割点、桥、圆方树
    割点与桥定义对于一个无向图,如果将一个点及其相连的边去掉后连通块数量增加,这个点就是割点;如果去掉一个边后连通块数量增加,这条边就是桥,也称割边。求法对无向图的每个......
  • 圆方树学习笔记
    部分内容参照了OI-wiki定义对于这样的一个无向图,左侧的\({1,2,3}\)和右侧的\({3,4,5}\)分别构成一个点双联通分量。中间的\(3\)号节点就是一个割点。不难发现,点双......
  • 圆方树
    OIwiki应该和这个差不多小粉兔blog例题CF1763FEdgeQueries题解↓这些题还没写,先留坑P4630[APIO2018]铁人两项CF487ETouristsP4606[SDOI2018]战略游戏P432......
  • CF487E Tourists(Tarjan,圆方树,树链剖分,线段树)
    CF487ETourists带权无向图\(N,M\),\(Q\)次询问\(s,t\)所有不经过重复点可能路径经过的最小值的最小值。CODE每次修改一个圆点\(u\)周围的方点有点难。可是李神......
  • 洛谷P4320 道路相遇(LCA+圆方树)
    题目链接:https://www.luogu.com.cn/problem/P4320道路相遇题目描述在H国的小w决定到从城市$u$到城市$v$旅行,但是此时小c由于各种原因不在城市$u$,但是小c决......