支配树(dominator tree)学习笔记
2017-02-27 08:14
169 查看
一些定义
idom(w)=max{v∣删掉v后没有从起点到w的路径} 记最近支配点idom(w)为iw,其意义如定义。
sdom(w)=min{v∣有一条路径v=v0,v1,⋯vk=w使得对于i∈[1,k)有vi>w}
记最远半支配点sdom(w)为sw,则sw的意义是dfs树上w的一个“最高分叉点”,也就是最浅的能够从“另一外一条路”绕到w的点。(这里我后来想了想感觉这么说也不太对。。。但是演算法笔记里面又是这么说的。。。有点不太懂sdom的意义了。。。可能的确只是一个辅助计算的东西吧。。。)
记图的起点为r。接下来讨论的图都是在有向图G=(V,E)的dfs树上的,点按照dfs序重标号。
u→˙v表示u是v的祖先,u−→+v表示u→˙v且$u\neq v$。
路径P(u,v)表示沿着树边从u走到v中间遇到的点的集合(不包括u,v)。
路径P[u,v]表示沿着树边从u走到v中间遇到的点的集合(包括u,v)。
路径P(u,v],P[u,v)同理。
一些性质
sw−→+w。首先至少w的父亲是一个半支配点,则sw不可能是比faw大的点。若sw不在祖先里,此时有一条sw→w的路径,与dfs树的性质矛盾。
iw→˙sw。
若iw不是w的祖先,则可以直接从r沿树边到w而不用经过w;若iw不是sw祖先,则sw处分出至少两条不相交路径,其中iw最多只能占一条,因此均矛盾。
iw−→+w。
由定义,显然。
若对于v,w有v→˙w,则iw∈P[v,w]或iw∈P[r,iv] 。
由定义,存在至少两条iv到v的不相交路径P1,P2,若iw∈P(iv,v),则iw不能同时位于这两条路径上,矛盾。
两个idom的确定定理
对于w≠r,若∀u∈P(sw,w]均有sw≤su,则iw=sw 。先说明sw支配了w。任取一条r到w的路径p,设x为路径中最后一个满足x<sw的点。如果不存在这样的x,也就意味着sw一定是路径中的起点,显然有sw支配w。 接着,令y为p在P[sw,w]中最的第一个点,再取q={x,v1⋯vk,y},那么有vi>y。这个考虑反证,若有vi<y,注意到在dfs树上一个小点走向大点的路径里一定会经过它们的LCA,取这个LCA为vj,因为x已经是最后一个x<sw的点了,而vj在x后,因此vj≥sw,又因为vj是y的祖先,所以有sw→˙vj→˙y→˙w,但这样与y是最早的P[sw,w]中的点矛盾,因此有vi>y 。这说明x可能成为y的半支配点,蕴含着sdom(y)≤x,而由假设有x<sw,因此sdom(y)<sdom(w),由条件知y只能是sw。这就说明了任何一条r到w路径都一定包含了sw 。
接下来说明sw是w最大的支配点。这个由上面的性质2可以立即得出。
对于w≠r,取u∈P(sw,w]中sdom最小的u,则su≤sw且iw=iu。
我们可以效仿上面的证明,任取一条路径,取第一个x<iu的x,如果不存在则显然iu已经支配了w;再取第一个y∈P[iu,w],注意到这里的条件已经被强化了,所以我们同样可以沿用上面的证明来说明sdom(y)≤x。那么这样就有一个关系图:sy≤x<iu≤su≤sw≤u≤w。但是现在我们还不知道y的位置,所以我们要尝试确定它。首先y一定不早P[sw,w]内,否则这就违反了su最小的前提;其次y也不会在P(iu,sw]内,否则就存在一条sy→y的路径且中间的点都大于y,这就避开了iu从而能到达u,矛盾;又由前提y∈P[iu,w]可得y=idom(u)。这样就说明了idom(u)一定在r→w的路径上。所以idom(w)=idom(u)。
显然这两个定理对于每个w都涵盖了所有的情况。
也就是说,我们先取P(sw,w]中sdom最小的记为u,若u=w,则idom(w)=sdom(w),否则idom(w)=idom(u) 。
sdom的确定定理
对于w≠r,有sdom(w)=min{{v∣(v,w)∈E且v<w}∩{sdom (u)∣u>w且存在边(v,w)使得u→˙v}}我们令等式右边为x,接下来的证明分成两部分。
先证明sdom(w)≤x。若x是在第一种集合里,由定义显然有sw≤x。考虑x在第二种集合里,则存在点u>w使得sdom(u)=x且有边(v,w)满足u\dot\rightarrow v。那么利用这个条件我们可以构造出一条x到w的路径,使得路径内经过的点都大于w,这说明x可能成为w的sdom,因此也有sdom(w)≤x。
然后证明sdom(w)≥x。我们取路径p={sw=v0,v1⋯vk=w且v1⋯vk−1>w}。若k=1,显然有sdom(w)≥x成立。否则在这条路径上取最小的一个点使得vj→˙vk−1,那么一定有v1⋯vj−1>vj,否则我们取最小的vi,其走到vj的路径一定会经过LCA(vi,vj),这是一条dfs树上由小指向大的路径,LCA一定不大于vi,而由前提可得LCA即为vi,这导出vi→˙vj,与前提矛盾,故v1⋯vj−1>vj。注意到这实际上是构造了一个vj满足了第二个集合里面的u,那么我们可以得到sdom(w)≥sdom(vj)≥x。
结合以上两个不等式,就得到了x=sdom(w)。
求sdom及idom
定义两个过程:* link(u,v)
* 将u设为森林中v的父亲。
* eval(u)
* 如果u是森林里的一个根则返回u,否则设根为r,返回P(r,u]上sdom最小的点。
利用这两个函数,根据上面的sdom确定定理,我们考虑从大到小来求sdom。对于扫到的每个w,我们计算sdom(w)=min{sdom(eval(v))∣(v,e)∈E}。考虑这个式子的正确性,当v<w时还没扫到v,eval(v)返回v;当v>w时,即是对应了sdom的式子里的第二个集合里的最小值。计算完sdom(w)之后,我们把w扔进sdom(w)的一个集合里,(Tarjan的论文中)记为bucket[sdom(w)]。接着就计算idom中的第一种情况,取bucket[fa(w)]中的所有点v,再取u=eval(v),若sdom(u)<sdom(v),说明此时的v不满足第一种情况,但是我们仍然计算出了第二种情况中的u,所以先记idom(v)=u;否则idom(v)=fa(w),即为第一种情况。这样扫完一遍之后,第二种情况中的v的idom还没完全求出,只需要顺着再扫一遍所有点直接求出即可。
时间复杂度
link直接连边eval的时候直接用路径压缩并查集的话时间复杂度是O(mlogn)的。通过神奇的link技巧可以降为O(mα(n,m))但是常数巨大跑起来和一个log差不多。。。带启发式合并的话具体还是看tarjan论文吧。。。代码实现
变量初值默认为0,图的起点为1。void dfs(int u) { sdom[u] = ++ dfs_clock; idx[dfs_clock] = u; label[u] = u; for (int v: G[u]) { if (!sdom[v]) dfs(v) , fa[v] = u; _G[v].pb(u); } } inline void compress(int u) { if (anc[anc[u]]) { compress(anc[u]); if (sdom[label[anc[u]]] < sdom[label[u]]) label[u] = label[anc[u]]; anc[u] = anc[anc[u]]; } } inline int eval(int u) { return anc[u] ? (compress(u) , label[u]) : u; } inline void link(int p , int u) { anc[u] = p; } void solve() { dfs(1); per (i , dfs_clock , 2) { int u = idx[i]; for (int v: _G[u]) upmin(sdom[u] , sdom[eval(v)]); int t = fa[u]; link(t , u) , bucket[idx[sdom[u]]].pb(u); for (int v: bucket[t]) { int w = eval(v); idom[v] = sdom[w] < sdom[v] ? w : t; } bucket[t].clear(); } rep (i , 2 , dfs_clock) { int u = idx[i]; if (idom[u] != idx[sdom[u]]) idom[u] = idom[idom[u]]; } }
几个题目
感觉都挺套路/裸的啊。。。不知道有没有啥有意思点的题。。。hdu 4694
直接求dom tree。。
Codechef GRAPHCNT
建出dom tree直接扫。。
2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest, Problem L
稍微有一点思考价值的题。。。但是知道这个要用dom tree的话结论是比较显然的。。。
References
其实基本上就是把tarjan的论文翻译了一遍而已hhhhhh1. THOMAS LENGAUER and ROBERT ENDRE TARJAN ,A Fast Algorithm for Finding Dominators in a Flowgraph .
2. TARJAN, R.E. Applications of path compression on balanced trees.
相关文章推荐
- 支配树(Dominator tree)学习笔记 及HDU4694Important Sisters
- 支配树(Dominator Tree)学习笔记
- flex 学习笔记 一个可以动态缩放的tree
- ALV TREE学习笔记
- Extjs学习笔记-1.TreePanel+TabPanel简单的树形菜单
- Extjs学习笔记--Ext.tree.Panel
- 《Pro Git 2》学习笔记_Chapter 10_Tree Objects&Commit_Objects
- Python学习笔记:Trie Tree的实现
- simple_tree学习笔记(二)----实现simple tree 中的double click事件
- Qt 学习笔记 TreeWidget 增删改
- stl源码剖析 详细学习笔记 RB_tree (2)
- openerp学习笔记 视图继承(tree、form、search)
- flex 学习笔记 tree的各个子级的颜色
- 正则表达式学习笔记(4) 贪婪、惰性和支配量词
- LigerUI学习笔记之二 Tree
- LLVM 的后序支配树(Post Dominator Tree)使用方法
- java学习笔记:集合框架之TreeSet
- java学习笔记:集合框架之TreeSet
- 【Java 学习笔记】 TreeMultimap(guava)
- stl源码剖析 详细学习笔记 RB_tree (1)