首页 > 其他分享 >支配树

支配树

时间:2023-12-13 22:56:25浏览次数:24  
标签:sdom 支配 int text leq idom

支配关系

给定一张有向图,钦定一个入口 \(s\),对于一个节点 \(u\), 若从 \(s\) 到 \(u\) 的每一条路径都经过某一个节点 \(v\) ,则我们称 \(v\) 支配 \(u\),记作 $v,\text{dom},u $,注意对于 \(s\) 不能到达的结点,其支配关系是无意义的,因此我们默认 \(s\) 能到达图上的所有节点

引理 1: \(s\) 是所有节点的支配点,任意一个节点都是自己的支配点

引理 2:仅考虑简单路径得出的支配关系与考虑所有路径得出的关系相同。

引理 3:如果 \(u\,\text{dom}\,v\),\(v\,\text{dom}\,w\) 则 \(u\,\text{dom}\,w\)

引理 4:如果 \(u\,\text{dom}\,v\),\(v\,\text{dom}\,u\),则 \(u=v\)

引理 5:若 \(u,v,w\) 两两不同,\(u\,\text{dom}\,w\) 且 \(v\,\text{dom}\,w\),则 \(u,v\) 之间一定存在支配关系

由上述引理,现对于所有除 \(s\) 之外的点 \(x\),我们考虑点集 \(S=\left\{y|y 支配 x\right\}\),则 \(S\) 中至少存在两个元素,因此一定存在一个点 \(z\) 满足 :如果 \(y\) 支配 \(x\) ,\(y\) 也支配 \(z\)。我们称 \(z\) 是 \(x\) 的直接支配点,记为 \(z=idom(x)\).

如果我们对于所有 \(x\) 连一条 \(idom(x)\rightarrow x\) ,则原图构成一颗 以 \(s\) 为根的树型结构,若 \(u\,\text{dom}\,v\) 当且仅当 \(u\) 是 \(v\) 的祖先,我们称此树型结构为支配树

支配树的求解

特殊图的支配树求解

1.树型图的支配树是其本身

2.DAG上,我们可以根据拓扑序求解,且前求得的解不会对后面产生影响

引理 6 ,在 DAG 上 点 \(y\,\text{dom}\,x\) 当且仅当 \(y=x\) 或 \(y\,\text{dom}\,S\) 其中 \(S=\left\{v|存在点 v\rightarrow x\right\}\)

反证法即可

换句话说,假设我们遍历到 \(x\) 节点时 ,已经构建了一颗包含之前所有节点的支配树,则\(idom(x)=LCA(idom(v_1)··· idom(v_n))\) ,相当于在支配树上加一个叶子,用倍增维护即可

3.一般图的支配树

首先有一个显然的 \(O(n^2)\) 做法,依次枚举删除哪个节点,用bfs 算出这个点支配多少点,则对于一个点,在能支配它的点中,被支配的集合最大的点即为 \(idom\)

为了更快的求解支配树,我们需要考虑更快的算法

之后的算法中我们要考虑任意一个图 \(G\) 的从 \(s\) 出发的 \(\text{DFS}\) 树,即进行深度优先遍历时经过的边形成的树结构,同时按照遍历顺序( \(\text{DFS}\) 序)为点赋予大小。具体来说对于两点 \(x\) , \(y\) ,如果 \(x\) 在遍历时比 \(y\) 访问的时间(即 \(\text{dfn}\) 序)更早,则称\(x < y\) ,类似地也可定义 \(x > y\) ,以及点集的最大值和最小值等相关概念,注意下文的所有大小关系均指 \(\text{dfn}\) 序上的大小关系

定理 1 如果 \(x\leq y\) ,则任意 \(x\) 到 \(y\) 的路径必须经过 \(x\) 和 \(y\) 在 \(\text{DFS}\) 树上的某个公共祖先

当 \(x\) 为 \(y\) 的祖先时结论显然,假设 \(x\) 不是 \(y\) 的祖先,假设存在一条路径 \(x = v_0, v_1, . . . , v_k = y\) ,其中不存在 \(x\) 和 \(y\) 在 \(\text{DFS}\) 树上的公共祖先。令 \(z\) 是 \(x\) 和 \(y\) 在 \(\text{DFS}\) 树上的最近公共祖先,\(z\) 的孩子中必有唯一一点 \(y′\) 是 \(y\)
的祖先,令 \(p=\max\left\{i|v_i<y^{'}\right\}\),假设其不是 \(z\) 的祖先 ,则 \(v_p\) 一定不是 \(v_{p+1}\) 的祖先,但又因为存在 \((v_p,v_{p+1})\) ,这与不是祖先矛盾,则 \(v_p\) 一定是 \(z\) 的祖先

下面定义半支配点

点 \(x\) 的 半支配点 \(sdom(x)=\min\left\{y|存在一条路径 y=v_0,v_1,...v_n=x\right\}\) ,满足对于任意的 \(1\leq i\leq k-1\) ,都有 \(v_i>x\)

引理 7 \(idom(x)\) 和 \(sdom(x)\) 都是 \(\text{DFS}\) 树上 \(x\) 的祖先且不等于 \(x\) ,更进一步的 ,在 \(\text{DFS}\) 树上的 \(idom(x)\) 是 \(sdom(x)\) 的祖先

证明 : \(idom(x)\) 显然,而 \(\text{DFS}\) 树上的父亲已经满足半支配点的祖先,所以 \(sdom(x)\) 也为 \(x\) 的祖先,而根据半支配点的定义,其选择的路径与 \(\text{DFS}\) 树上的路径完全不同,所以在 \(\text{DFS}\) 树上的路径从 \(sdom(x) 到 x\) 之间(不包含端点)都不支配 \(x\),所以\(idom(x)\) 是 \(sdom(x)\) 的祖先

引理 8,令 \(v, w\) 满足 \(\text{DFS}\) 树上 \(v\) 是 \(w\) 的祖先,则 \(v\) 是 \(idom(w)\) 的祖先或 \(idom(w)\) 是 \(idom(v)\) 的祖先

证明:因 此 假 设 \(v\) 和 \(w\) 不相同 。 使 用 反 证 法, 由 于\(v, w, idom(v), idom(w)\) 都是 \(w\) 的祖先,如果引理中的结论不成立,则它们按深度排序依次是 $ idom(v), idom(w), v, w$ 且它们互不相等。这意味着存在一条不经过 \(idom(w)\) 的从 \(s\) 到 \(v\) 的路径,继续沿 \(\text{DFS}\) 树走到 \(w\) 就得到一条不经过\(idom(w)\) 的从 \(s\) 到 \(w\) 的路径,矛盾

由上我们可以得出一个十分重要的定理

定理 2 \(sdom(u)=\min(\left\{v|存在v\rightarrow u 且 v<u\right\}\cup\left\{sdom(w)|w 是 v 在 DFS 树上的祖先,w > u 且有边 (v, u) \right\})\)

证明 令 \(x\) 等于右式

首先由 \(sdom(u)\leq x\) ,前半部分显然为一个半支配点的候选集合,后半部分我们考虑将定义中 \(sdom(w)\) 到 \(w\)

的路径接上 \(\text{DFS}\) 树上的路径再接上 \((v,u)\) 这条边,则这条边显然是一条半支配点路径

还需证明 \(sdom(u)\geq x\) ,考虑 \(sdom(w)\) 到 \(w\) 的半支配点对应的路径 \(v_0=sdom(w),v_1,...,v_k=w\) ,设 \(k>1\) ,取最小的 \(j\geq 1\) 且 \(v_j\) 是 \(v_{k-1}\) 在 \(\text{DFS}\) 树上的祖先的数,则 \(j\) 一定存在

考虑路径 \(v_0,...v_j\) ,我们断定它是一条满足半支配点的路径,若不是,考虑取\(v_i\leq v_j\) 中 \(v_i\) 最小的 \(i\) ,则一定有定理 2 得其一定为 \(v_j\) 得祖先,与 \(j\) 得选取矛盾,所以断言成立,则有 \(sdom(v_j)\leq sdom(w)\) 而 \(sdom(v_j)\) 在情况二中被考虑到 ,因此证明成立

至此,我们可以利用带权并查集以 \(O((n+m)\log n)\) 的时间快速维护每个点的半支配点

半支配点关于支配点有着十分优美的性质,具体如下

定理二 任取点 \(w\ne s\) 。考虑 \(\text{DFS}\) 树上从 \(sdom(w)\) 到 \(w\) 的路径上(不包括 \(sdom(w)\) )的任意点 \(x\),如果均满足 \(sdom(x) ≥ sdom(w)\) ,则 \(idom(w) = sdom(w)\)

证明 由 引理 7 可得 \(idom(w)\) 为 \(sdom(w)\) 的祖先,我们只需证明 \(sdom(w)\) 支配 \(w\),考虑任意一条 \(s\) 到 \(w\) 的路径 \(P\),我们应证明 \(sdom(w)\) 一定在 \(P\) 中 ,令 \(x\) 为 \(P\) 中最后一个满足 \(x<sdom(w)\) 的点,若不存在则必有 \(sdom(w)=idom(w)=s\) 。若存在,令 \(y\) 为 \(P\) 中 \(x\) 之后的第一个在 \(DFS\) 树中从 \(sdom(w)\) 到 \(w\) 路径上的点,并在 \(P\) 中截取 \(x\) 到 \(y\) 之间的部分 \(v_0=x,v_1,...v_k=y\)

考虑该路径,我们声称 \(1\leq i<k\) 都有 \(v_i>y\),即 \(sdom(y)\leq x\),假使不满足,则有 \(v_i\leq y\) ,由定理 1可知一定存在 \(i\leq j\leq k-1\) 满足 \(v_j\) 是 \(y\) 的祖先,由 \(x\) 的取值可知 \(sdom(w)\leq v_j\),于是有 \(v_j\) 也在 \(sdom(w)\) 到 \(w\) 的路径上,与 \(y\) 的取值矛盾。所以可知 \(sdom(y)\leq x <sdom(w)\) 而定理条件有\(sdom(x) ≥ sdom(w)\),所以 \(y\) 一定为 \(sdom(w)\)

定理三 任取点 \(w \ne s\) 。考虑 \(\text{DFS}\) 树上从 \(sdom(w)\) 到 \(w\) 的路径上(不包括 \(sdom(w)\)的所有点,令 \(u\) 是其中 \(sdom\) 最小的点,则 \(sdom(u) ≤ sdom(w)\) 且\(idom(u) = idom(w)\) 。

证明 ,由于 \(w\) 也是 \(u\) 的一个候选,则 \(sdom(u)\leq sdom(w)\),注意到 \(idom(w)\) 是 \(u\) 的祖先,有引理 8 可知 \(idom(w)\) 也是 \(idom(u)\) 的祖先,只需证明 \(idom(u)\) 支配 \(w\),考虑一条 \(s\) 到 \(w\) 的路径 \(P\) ,我们将要证明 \(idom(u)\) 一定在 \(P\) 中,令 \(x\) 是 \(P\) 中最后一个满足 \(x<idom(u)\) 的点,若不存在则必\(idom(w)=idom(w)=s\) 。若存在,令 \(y\) 为 \(P\) 中 \(x\) 之后的第一个在 \(DFS\) 树中从 \(idom(w)\) 到 \(w\) 路径上的点,并在 \(P\) 中截取 \(x\) 到 \(y\) 之间的部分 \(v_0=x,v_1,...v_k=y\)

和定理 2 的证明类似,仍然有 \(sdom(y)\leq x\) ,有引理 2 可知有 \(idom(u)\leq sdom(u)\) ,即有 \(sdom(y)\leq x<idom(u)<sdom(u)\),可知 \(y\) 不能是 \(sdom(w)\) 的除自身外的后代;另一方面,\(y\) 不能既是 \(idom(u)\) 的除自身外后代也是 u 的祖先,否则沿 DFS 树从 \(s\) 走到 $sdom(y) $再沿 P 走到 y,最后沿 \(\text{DFS}\) 树走到\(u\) 的这条路径就不经过$ idom(u)$ 了,这和支配点的定义矛盾,则情况只剩下了 \(y=idom(u)\) 了

复杂的证明,其实总结起来就几句话

1.\(sdom(u)\)的计算式

\(sdom(u)=\min(\left\{v|存在v\rightarrow u 且 v<u\right\}\cup\left\{sdom(w)|w 是 v 在 DFS 树上的祖先,w > u 且有边 (v, u) \right\})\)

2.\(idom(u)\) 的计算式(令\(v\) 为 \(sdom(u)\) 和 \(u\) 之间,\(sdom(v)\) 最小的节点)

\(idom(u)=\begin{cases}sdom(u)&sdom(v)\geq sdom(u)\\idom(v)&sdom(v)<sdom(u)\end{cases}\)

这就可以写代码了

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long 
char buf[1<<21],*p1,*p2;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
long long rd()
{
	long long res=0,f=1;char ch;
	for(ch=getchar();ch<'0'||ch>'9';ch=getchar())
		if(ch=='-') f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())
		res=(res<<3)+(res<<1)+ch-'0';
	return res*f;
}
void wt(int x,char ch=0)
{
	if(x<0) putchar('-'),wt(-x);
	else
	{
		if(x>=10) wt(x/10);
		putchar(x%10+'0');
	}
	if(ch) putchar(ch);
	return ;
}
struct edge{
	int to,nex;
}e[840010];
int head[500100],cnt;
void add(int u,int v)
{
	e[++cnt]={v,head[u]};
	head[u]=cnt;
}
int n,m,dfncnt;
int ans[500100],dfn[500100],rnk[500100],sdm[500100],idm[500100],fa[500100],mn[500100];
int f[500100];
vector<int>vc[2][500100];
void dfs(int now,int fath)
{
	dfn[now]=++dfncnt;
	rnk[dfncnt]=now;
	f[now]=fath;
	for(int i=head[now];i;i=e[i].nex)
	{
		int v=e[i].to;
		if(!dfn[v])
		{
			dfs(v,now);
		}
	}
}
int find(int x)
{
	if(x==fa[x]) return fa[x];
	int tmp=fa[x];
	fa[x]=find(fa[x]);
	if(dfn[sdm[mn[tmp]]]<dfn[sdm[mn[x]]])
	{
		mn[x]=mn[tmp];
	}
	return fa[x];
}
void tar(int st)
{
	dfs(st,0);
	for(int i=1;i<=n;i++)
	{
		mn[i]=fa[i]=sdm[i]=i;
	}
	for(int i=dfncnt;i>=2;i--)
	{
		int u=rnk[i],res=0x3f3f3f3f;
		for(int j=0;j<(int)(vc[0][u].size());j++)
		{
			int v=vc[0][u][j];
			if(!dfn[v]) continue;
			find(v);
			if(dfn[v]<dfn[u])
			{
				res=min(res,dfn[v]);
			}
			else 
			{
				res=min(res,dfn[sdm[mn[v]]]);
			}
		}
		sdm[u]=rnk[res];
		fa[u]=f[u];
		vc[1][sdm[u]].push_back(u);
		u=f[u];
		for(int j=0;j<(int)vc[1][u].size();j++)
		{
			int v=vc[1][u][j];
			find(v);
			if(dfn[sdm[mn[v]]]>=dfn[u])
			{
				idm[v]=u;
			}
			else idm[v]=mn[v];
		}
		vc[1][u].clear();
	}
	for(int i=2;i<=dfncnt;i++)
	{
		int u=rnk[i];
		if(idm[u]!=sdm[u])
		{
			idm[u]=idm[idm[u]];
		}
	}
	for(int i=dfncnt;i>=2;i--)
	{
		++ans[rnk[i]];
		ans[idm[rnk[i]]]+=ans[rnk[i]];
	}
	ans[1]++;
}
signed main()
{
    // freopen("txt.in","r",stdin);
    // freopen("txt.out","w",stdout);
    // ios::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		add(u,v);
		vc[0][v].push_back(u);
	}
	tar(1);
	for(int i=1;i<=n;i++)
	{
		cout<<ans[i]<<" ";
	}
    return 0;
}

标签:sdom,支配,int,text,leq,idom
From: https://www.cnblogs.com/L-fire/p/17900127.html

相关文章

  • 控制流图+支配树
    编译器优化记录(1)0.为啥要写这个记录我感觉自己平时整理自己想法的机会实在是太少了。即便是对于自己花了很多时间想、或是花了很多时间学的东西,同样如此。写编译器优化的阶段学了很多方法,也看到了很多人类智慧,我希望能从头梳理一下认识它们的过程,来更好地体悟。我身边有几位......
  • 「黑科技」支配树
    定义给定一张有向图与一个起点\(s\),如果要去掉起点\(s\)到某个点\(v\)的中间的某个点\(u\)后无法到达,那么称点\(u\)支配点\(v\),\(u\)是\(v\)的一个支配点最近支配点\((idom[u])\)\(u\)的支配点中距离\(u\)最近的一点支配树由所有边\(idom[u]\rightar......
  • MATLAB程序采用非支配排序遗传算法(NSGA2)求解分布式电源选址定容问题,可作为一个有用的
    MATLAB程序采用非支配排序遗传算法(NSGA2)求解分布式电源选址定容问题,可作为一个有用的参考,程序注释明确,算法原理可以自己搜。YID:4120651507678049......
  • MATLAB程序采用非支配排序遗传算法(NSGA2)求解分布式电源选址定容问题,可作为一个有用的
    MATLAB程序采用非支配排序遗传算法(NSGA2)求解分布式电源选址定容问题,可作为一个有用的参考,程序注释明确,算法原理可以自己搜。YID:4120651507678049......
  • luogu P7520 [省选联考 2021 A 卷] 支配
    题面传送门自己瞎胡的支配树,可能是错的(大雾首先我们可以证明,支配关系成树。考虑一个点\(x\)的两个受支配点\(y,z\),这两个点应该在一条路径上,如果\(y,z\)之间没有支......
  • 【学习笔记】支配树
    先对自己说句话:你觉得没用的算法不一定没用,别太自以为是在那里一遍一遍叫"stoplearninguselessalgorithm",最useless的是你。支配给定一个有向图\(G\),有一个起点......
  • 基于matlab的最小支配集CDS仿真
    1.算法描述       支配集的定义如下:给定无向图G=(V,E),其中V是点集,E是边集,称V的一个子集S称为支配集当且仅当对于V-S中任何一个点v,都有S中的某个点u,使得(u,......
  • 【XSY2418】修路(最短路图,支配)
    首先可以\(O(m\logn)\)按题意把树建出来,显然这是一棵最短路图的生成树。那么询问\(u,v\)相当于在树上\((u,v)\)路径上找到深度最深的一点\(w\),满足最短路图中刨掉......
  • 2020年人均可支配收入(同志们,你们已经很棒了)
    中新网1月18日电据国家统计局网站消息,2020年,全国居民人均可支配收入32189元,比上年名义增长4.7%,扣除价格因素,实际增长2.1%。其中,城镇居民人均可支配收入43834元,增长(以下如......
  • CCPC Finals 2021 H Harie Programming Contest (网络流&支配树的妙用)
    Link题意:给一个二分图,求有多少种方案删去恰好两个点,使得最大匹配数不变。\(n,m\le2\times10^5\)。二话不说先跑一遍Dinic网络流,设残量网络形成的图为\(G\)。然后......