zoukankan      html  css  js  c++  java
  • [学习笔记]支配树

    支配树(DominatorTree)

    对于一个流程图,单源有向图,上点\(w\),如果去掉一个点\(d\),使得源点无法到达则称其支配\(w\)

    image

    通过定义,我们知道支配的这个定义,满足传递性。

    定理一:

    除源点外所有点均有单一的最近支配点。

    且我们知道如果我们找到最近的支配点\((immediate dominator)\),\(idom(w)\),以源点作为祖先,将其构成树,则满足一个点的祖先链上全为其的支配点。

    image

    支配树相关性质:

    我们随便选择一颗生成树。

    image

    下列的所有比较均为\(dfn\)序比较。

    引理一:路径原理:
    如果两个点满足\(v \leq w\),那么所有\(v\)\(w\)的路径经过其公共祖先。

    符号规定

    下列规定一些符号:

    \(a\to b\)代表点\(a\)直接经过一条边到达点\(b\)

    \(a \rightsquigarrow b\)代表点\(a\)经过某条路径到达点\(b\)

    \(a \stackrel{。}{\to} b\)代表经过DFS树到达点\(b\)

    \(a \stackrel{+}{\to} b\)代表\(a \stackrel{。}{\to} b\)\(a \neq b\)

    定义半支配点

    对于\(w\neq r\),他的半支配点\((semi-dominator)\)定义为\(sdom(w) = \min{v|\exists (v_0,v+1,...v_{k - 1},v_k),v_0 = v,v_k = w,\forall(i\neq 0) v_i > w}\)

    引理2:对于任意\(w \neq r\),有\(idom(w) \stackrel{+}{\to} w\)

    引理3:对于任意\(w \neq r\),有\(sdom(w) \stackrel{+}{\to} w\)

    引理4:对于任意\(w \neq r\),有\(idom(w) \stackrel{。}{\to} sdom(w)\)
    证明:考虑若不如此,则存在一条\(r \stackrel{。}{\to} sdom(w) \rightsquigarrow w\),与\(idom\)定义矛盾。

    引理5:对于满足\(v \stackrel{。}{\to} w\),\(v \stackrel{。}{\to} idom(w)\)\(idom(w) \stackrel{。}{\to} idom(v)\)
    证明:如果不是这样:该情况为:\(idom(v) \stackrel{+}{\to} idom(w) \stackrel{+}{\to} v\stackrel{+}{\to} w\),那么存在路径\(r \stackrel{。}{\to} idom(v) \rightsquigarrow v \stackrel{+}{\to} w\),不经过\(idom(w)\)到达了\(w\),因为\(idom(w)\)\(idom(v)\)的真后代,一定不支配\(v\)

    前面几条引理较为简单。

    后面我们来证明一些较为复杂的定理。

    定理二:

    image

    定理三:

    image

    推论一:

    image

    接下里考虑如何快速求出\(sdom\)

    定理四:

    image

    Lengauer-Tarjan算法

    算法有四步:
    一:先跑出\(DFS\)
    二:利用定理四从大到小求出\(sdom\)
    三:通过推论一求出所有能确定的\(idom\),否则记录和哪个点的\(idom\)相同
    四:从小到大跑出所有的点的\(idom\)

    细节:
    image

    支配树
    #include<bits/stdc++.h>
    #define ll long long 
    #define N 200005
    
    using std::vector;
    
    int n,m;
    
    vector<int>to[N];
    vector<int>in[N];
    vector<int>buk[N];
    int head[N];
    
    int sdom[N],idom[N];
    
    int fa[N];
    int eval[N];
    
    //DSU
    
    int dfn[N],cnt;
    int inv[N];
    int F[N];
    int vis[N];
    //tree 
    
    inline void dfs(int u){
    	vis[u] = 1;
    	dfn[u] = ++cnt;
    	sdom[u] = dfn[u];
    	inv[dfn[u]] = u;
    	for(int i = 0;i < to[u].size();++i){
    		if(!vis[to[u][i]]){
    			int v = to[u][i];
    			F[v] = u;
    			dfs(v);
    		}
    	}
    }
    
    //sdom : dfn eval : point idom : point
    
    inline int find(int u){
    	if(fa[u] == u)return u;
    	int f = find(fa[u]);
    	if(sdom[eval[fa[u]]] < sdom[eval[u]])
    	eval[u] = eval[fa[u]];
    	return fa[u] = f; 
    }
    
    inline void merge(int x,int y){//x -> y
    //	std::cout<<"("<<x<<"->"<<y<<")"<<std::endl;
    	fa[x] = y;
    }
    
    inline void delta(int u){
    	for(;head[u] < buk[u].size();++head[u]){
    		int v = buk[u][head[u]];
    		int f = find(v);
    		if(sdom[eval[v]] == sdom[v])
    		idom[v] = u;
    		else
    		idom[v] = eval[v];
    	}
    }
    
    inline void del(int u){
    	for(int i = 0;i < in[u].size();++i){
    		int v = in[u][i];
    		int f = find(v);
    		sdom[u] = std::min(sdom[u],sdom[eval[v]]);
    	}
    	buk[inv[sdom[u]]].push_back(u);
    	merge(u,F[u]);
    	delta(F[u]);
    }
    
    //Dom tree
    
    vector<int>A[N];
    
    int siz[N];
    
    inline void serch(int u){
    	siz[u] = 1;
    	for(int i = 0;i < A[u].size();++i)
    	serch(A[u][i]),siz[u] += siz[A[u][i]];
    }
    
    int s;
    
    int main(){
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i = 1;i <= n;++i)
    	fa[i] = i,eval[i] = i;
    	for(int i = 1;i <= m;++i){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		x ++ ,y ++ ;		
    		to[x].push_back(y);
    		in[y].push_back(x);
    	}
    	dfs(s + 1);
    	for(int i = n;i >= 2;--i){
    		int u = inv[i];
    		del(u);//find_sdom
    	}
    	for(int i = 1;i <= n;++i){
    		int u = inv[i];
    		if(idom[u] != inv[sdom[u]])
    		idom[u] = idom[idom[u]];
    	}
    	for(int i = 1;i <= n;++i)
    	std::cout<<idom[i]<<" ";
    }
    
  • 相关阅读:
    WINXP下安装IIS+PHP5+MySQL5 +Apache
    centos下配置apache+php+mysql!
    在C#中如何调用记事本
    使用c#捕获windows的关机事件(转载)
    C# WinForm中DataGrid列设置(转载)
    软件开发五要五不要原则
    ASP.NET2.0中将文件上传到数据库(转载)
    如何用C#和ADO.NET建立一个数据绑定网格(转载)
    SQL基础:常用SQL语句详解
    什么是极端编程?
  • 原文地址:https://www.cnblogs.com/dixiao/p/15789283.html
Copyright © 2011-2022 走看看