支配树(Dominator Tree)学习笔记
来源:互联网 发布:matlab centos ubuntu 编辑:程序博客网 时间:2024/05/12 15:45
因为是学习笔记所以是边学边写,以防自己到时候忘掉了=w=
一些定义和性质
首先,支配树是一棵树(废话),用来求解必经点问题。
即求一个有向图中以r为根到达每一个点的必经点。
树中每一个点x的父亲为idom(x),表示x的最近必经点。
我们把从r到x必经y称作“y支配x”,显然支配是具有传递性的。
所以可以证明idom是唯一的。
首先对原图G建出其的dfs树T并且按dfs序重标号,那么就具有一些性质:
1:横叉边必然从大指向小
这就表明对于任意两点u,v,u<=v,u到v中的任意路径都经过u,v在T中的一个公共祖先
2:idom(x)必为x在T中的祖先
废话
定义半必经点sdom(x),表示最小的v,使得存在一条从v到x的路径不经过任何树边。
3:sdom(x)必为x在T中的祖先
因为sdom(x)<=x,根据性质1可知sdom(x)到x的那条路径必然经过x和sdom(x)的一个公共祖先。而这个公共祖先就是sdom(x)。如果不是就证明sdom(x)是通过横叉边走到x的祖先中,这显然是不合法的。
4:idom(x)必为sdom(x)在T中的祖先
二者都是x的祖先,并且idom(x)不可能为sdom(x)的后代,否则将被完全跳过。
5:如果v是x的祖先,那么v是idom(x)的祖先或者idom(x)是idom(v)的祖先。
如果v是idom(x)的后代,并且idom(v)是idom(x)的祖先,那么就可以从r绕过idom(x)走到v,再直接走到x,与已知矛盾。
求解Sdom
接下来讲如何求sdom(x)
先给出结论,对于x的一个前继y,若y < x,sdom(x)=min(y)
否则sdom(x)=min(sdom(z)),z是y的祖先且z > x
证明:设右边的数为v,先证明sdom(x)<=v,再证明sdom(x)>=v
1”,对于第一种显然成立
第二种,存在一条从sdom(z)到z到y到x的路径
其中sdom(z)到z这一段除头尾均>z,即>x
后一段显然
所以证明了sdom(x)<=v
2”如果sdom(x)只经过一条边,必有sdom(x)>=v,因为v<=min(y),y是x的前继
否则我们设路径v0=sdom(x),v1,v2,v3…vk=x,vj是首个满足vj是vk-1的父亲的。
可以证明v1…vj-1>vj,否则我们取最小的vi满足vi < vj,必然满足vi到vj的路径上经过vi和vj的一个祖先,设为w,可以通过类似性质3的证明发现w就是vi,那么vi是vj的祖先,也就是vi是vk-1的祖先,与假设矛盾。
这其实就是构造了一个集合满足第二种条件,vj相当于z,于是sdom(x)=sdom(vj)>=v,因为我们的路径是任取的,并且对于所有的路径都满足条件。
综上sdom(x)=v
求解idom
说了这么多我们就是要用sdom来求idom
其实我们发现如果我们将所有的边
具体来说idom(x)=LCA(idom(y)),y是x的前继。
但是tarjan提出了一个叫做Lengauer-Tarjan的利用并查集达到O(nα(n))的做法
让我们再来讲几个用sdom求idom的定理:
1:若所有在sdom(x)到x的路径上的点y,y!=sdom(x)都满足sdom(y)>=sdom(x)则idom(x)=sdom(x)
证明:对于任意一条r到x的路径,设点z为最后一个小于sdom(x)的点。
若没有则显然sdom(x)支配x
设w为路径上z之后首个在sdom(x)到x路径上的点(不含端点)
类似sdom的证明,路径上z到w的点vi>w
所以sdom(w)<=z < sdom(x)
又因为条件知道sdom(w)>=sdom(x),所以w不能是sdom(x)的后代,与假设矛盾。
2:令u是sdom(x)到x的路径上的sdom(u)最小的点,u!=sdom(x)
则idom(x)=idom(u)
证明:类似上一个的证明形式,取最后一个点z满足z < idom(u)
再取第一个y满足y在idom(u)到x的路径上。
同理可得sdom(y)<=z,那么我们知道sdom(y)<=z < idom(u)<=sdom(u)<=sdom(x) < u<=x
现在我们来尝试确定y的位置。
首先y一定不在sdom(x)到x的路径上,如果在就违反了sdom(u)最小
其次y一定不再idom(u)到sdom(x)的路径上,如果在我们就存在一条从r到sdom(y)到y避开idom(u)到u的路径。
这样就说明了y=idom(u),即idom(u)支配x
也就是说,我们取从sdom(x)到x路径上sdom(u)最小的u,如果u=x,那么idom(x)=sdom(x),否则idom(x)=idom(u)
Lengauer-Tarjan
首先考虑求sdom的做法,我们只需要求出对于点x所有大于他的祖先。
考虑按dfs序倒序处理,用带权并查集维护,很容易处理出sdom最小的那个点。
对于idom来说,我们每处理完一个点的sdom,就把它挂在sdom处。
然后处理所有挂在它父亲处的点v,求出点v到r路径上目前sdom最小的点设为u。
如果sdom(u) < sdom(v),说明此时v不满足第一种情况,但是u是对于v来说第二种情况的候选点,并且由于我们是倒序枚举u一定当前最小,我们直接把idom(v)设为u。
否则idom(v)=fa(x),这是由于第一种情况。
当我们做完之后会发现第二种情况我们的idom实际上求的是候选点而不是idom
所以再扫一遍把所有的idom求出来即可。
Code
例题:HDU 4694 Important Sisters
typedef vector<int> vec;#define pb(a) push_back(a)vec pre[N],dom[N];int lst[N],nxt[N<<1],t[N<<1],l;void add(int x,int y) { t[++l]=y;nxt[l]=lst[x];lst[x]=l;}int n,m,x,y,semi[N],idom[N];int id[N],dfn[N],fa[N],tot;void dfs(int x) { dfn[x]=++tot;id[tot]=x; rep(i,x) { pre[t[i]].pb(x); if (!dfn[t[i]]) { fa[t[i]]=x; dfs(t[i]); } }}int father[N],val[N];int get(int x) { if (father[x]==x) return x; int y=get(father[x]); if (dfn[semi[val[father[x]]]]<dfn[semi[val[x]]]) val[x]=val[father[x]]; return father[x]=y;}int smin(int x,int y) {return dfn[x]<dfn[y]?x:y;}void solve() { fd(i,tot,2) { int x=id[i]; if (!pre[x].empty()) fo(j,0,pre[x].size()-1) if (dfn[pre[x][j]]<dfn[x]) semi[x]=smin(semi[x],pre[x][j]); else { get(pre[x][j]); semi[x]=smin(semi[x],semi[val[pre[x][j]]]); } father[x]=fa[x];dom[semi[x]].pb(x); if (!dom[fa[x]].empty()) fo(j,0,dom[fa[x]].size()-1) { int v=dom[fa[x]][j];get(v); int u=val[v]; idom[v]=(dfn[semi[u]]<dfn[semi[v]])?u:fa[x]; } } fo(i,2,tot) { int x=id[i]; if (idom[x]!=semi[x]) idom[x]=idom[idom[x]]; }}
参考资料:WC营员交流 王梦迪-支配树
- 支配树(dominator tree)学习笔记
- 支配树(Dominator Tree)学习笔记
- 支配树(Dominator tree)学习笔记 及HDU4694Important Sisters
- LLVM 的后序支配树(Post Dominator Tree)使用方法
- 支配树学习笔记
- 学习一个支配树
- 学习一个支配树
- 构造Dominator Tree以及Dominator Frontier
- 【dominator tree】 Lengauer-Tarjan algorithm
- 正则表达式学习笔记贪婪、惰性和支配量词
- 【学习笔记】 支配集、覆盖集、独立集与匹配
- Codechef GRAPHCNT 支配树学习及tarjan算法求解
- HDU 4694 [支配树]
- 支配树[模板]
- 【拓扑排序+LCA构造Dominator Tree】BZOJ2815 [ZJOI2012]灾难
- 正则表达式学习笔记(4) 贪婪、惰性和支配量词
- 正则表达式学习笔记(4) 贪婪、惰性和支配量词
- 学习笔记-动态树Link-Cut-Tree
- 2321: [BeiJing2011集训]星器
- 修复dede织梦undefined function pasterTempletDiy报错
- Java 运算符
- PHPEXCEl
- TensorFlow技术解析与实战 6 神经网络的发展及其 TensorFlow 实现
- 支配树(Dominator Tree)学习笔记
- Android性能优化一:布局性能优化
- 主席树(资料整理+深刻理解)(静态)
- Kaldi决策树状态绑定学习笔记
- DEDE自由列表的"不使用目录默认主页"错误修正
- gbk版织梦在php5.4下系统基本设置不能保存中文以及在编辑器下中
- 僵尸进程和孤儿进程
- ORB_SLAM2系列之四:利用华硕Xtion Pro Live跑ORB_SLAM2
- docker下启动jenkins命令