支配树

何为支配树?

  定义:

    支配点:在一张图中起点为s,如果有一个点t,使得删去t后没有s到w的路径(不包含w本身),则称t为w的支配点
    最近支配点:记最近支配点为idom(w),下文简称iw。它是所有w的支配点中离w最近的(dfn值最大的,在dfs树中为w的祖先)

    半支配点:存在一条t到w的路径,使得路径中除了t和w,其他的点dfn值都比w的大,则t为w的半支配点。
    注:所有能直接到w的点都是半支配点
    最远半支配点:记最远半支配点为sdom(w),下文简称sw。它是所有w的半支配点中离w最远的(dfn值最小的)

    支配树即为一棵根为起点s,其他的点连向它的最近支配点的树。
    在原图上删去一个点后,起点和各个点的联通情况=在支配树中删去这个点,起点和各个点的联通情况
    (这里联通情况指单向的,及只表示起点是否能到各个节点)

建造方法

  声明:

    路径P(u,v)表示沿着树边从u走到v中间遇到的点的集合(不包括u,v)。
    路径P[u,v]表示沿着树边从u走到v中间遇到的点的集合(包括u,v)。
    路径P(u,v],P[u,v)同理。

  一些性质(在图的dfs树上):

    1.sw为w的祖先
    证明:首先sw的dfn小于w的dfn,否则sdom(sw)也是w的半支配点并且dfn比sw要小。
    其次,假设sw不是w祖先且dfn[sw]<dfn[w],则一定是先搜sw,回溯后才继续搜索的w,但sw可以直接搜索到w,所以假设不成立

    2.iw为w的祖先
    证明:若iw不为w祖先,则可以直接从dfs树边到w且不经过iw。

    3.iw为sw或sw的祖先
    证明:假设不是,则iw为sw的后代,但sw可以有至少两条不相交的路径到w,iw只能在其中一条上

    4.对于w的祖先v,iw∈P[v,w]或iw∈P[r,iv]
    证明:假设不是,则iv到v至少有两条不相交的路径,iw只能在其中一条上,删掉iw从iv依然可以到v,即从s可以到w

  idom的确定定理

    1、对于w≠r,若∀u∈P(sw,w]均有sw≤su,则iw=sw 。

    证明:首先在sw下面没有支配w的点了(若sw支配w,则sw为iw)

    然后先说明sw支配了w。任取一条r到w的路径p,设x为路径中最低的不经过sw能到P(sw,w]的点(一定是dfs树中sw的祖先)。
    如果不存在这样的x,也就意味着sw一定是路径中的起点,显然有sw支配w。
     接着,令y为在P[sw,w]中第一个不受sw支配的点,再取q={x,v1⋯vk,y}(且不经过sw),那么有vi>y。
    (若vi<sw则x不是最低的不经过sw能到P(sw,w]的点,vi才是,若sw<vi<y,则y不是p在P[sw,w]中第一个不受sw支配的点,vi才是)
    这说明x是y的半支配点,蕴含着sdom(y)≤x,而x<sw,因此sdom(y)<sdom(w),由条件知不存在这样的x,y。
    这就说明了任何一条r到w路径都一定包含了sw 。

    2、对于w≠r​,取u∈P(sw,w]​中sdom​最小的u​,则su≤sw​且iw=iu​。

    证明:我们可以效仿上面的证明,任取一条r到w的路径p,设x为路径中最低的不经过iu能到P(iu,w]的点(一定是dfs树中sw的祖先)
    如果不存在则显然iu已经支配了w;令y为在P[iu,w]中第一个不受iu支配的点,再取q={x,v1⋯vk,y}(且不经过iu),那么有vi>y。
    这说明x是y的半支配点,蕴含着sdom(y)≤x,而x<sw,因此sdom(y)<sdom(w),由条件知不存在这样的x,y。所以iu支配w。
    然后取P(iu,w]中任何一点,显然都不支配w。所以iw=iu。

  确定sdom

    sdom(w)=min{{v∣(v,w)∈E且v<w}∪{sdom (u)∣u>w且存在边(v,w)使u为v或v的祖先}}(根据定义即可得到)

代码实现

#include<cstdio>
#define maxn 100005
#define maxm 500005
struct Edge{
    int next,to;
}edge[maxm],edge_pr[maxm],road[maxn];
int n,m,fi[maxn],se,fi_pr[maxn],se_pr,dfn[maxn],si,a[maxn],fa[maxn],head[maxn],sr;
int sdom[maxn],idom[maxn],myfind[maxn],mi_sdom[maxn],son[maxn];
inline void add_edge(int u,int v){//存图的边 
    edge[++se].next=fi[u],edge[se].to=v,fi[u]=se;
}
inline void add_edge_pr(int u,int v){//存图的反向边 
    edge_pr[++se_pr].next=fi_pr[u],edge_pr[se_pr].to=v,fi_pr[u]=se_pr;
}
inline void add_road(int u,int v){//指向sdom为自己的点 
    road[++sr].next=head[u],road[sr].to=v,head[u]=sr;
}
void dfs(int x){//预处理出dfs树 
    a[dfn[x]=++si]=x;
    for(int i=fi[x];i;i=edge[i].next){
        int v=edge[i].to;
        if(!dfn[v])dfs(v),fa[v]=x;
    }
}
int Find(int x){//带权并查集路径压缩 
    if(x==myfind[x])return x;//dfn小于正在求的点,返回自己 
    int y=Find(myfind[x]);//返回祖先中dfn小于正在求的点的最深的点 
    if(dfn[sdom[mi_sdom[myfind[x]]]]<dfn[sdom[mi_sdom[x]]])mi_sdom[x]=mi_sdom[myfind[x]];//更新dfn大于正在求的点的最小的sdom 
    return myfind[x]=y;
}
inline void build(){
    for(int i=1;i<=n;i++)myfind[i]=sdom[i]=mi_sdom[i]=i;
    dfs(1);
    for(int j=si;j>1;j--){//必须按dfs序倒着算 
        int x=a[j];
        for(int i=fi_pr[x];i;i=edge_pr[i].next){//v为能到达x的点 
            int v=edge_pr[i].to;
            if(!dfn[v]) continue;
            Find(v);
            if(dfn[sdom[mi_sdom[v]]]<dfn[sdom[x]])sdom[x]=sdom[mi_sdom[v]];
            //若dfn[v]<dfn[x]则sdom[mi_sdom[v]]==v,否则sdom[mi_sdom[v]]为sdom (u)使得u为v的祖先,于是可求出sdom 
        }
        add_road(sdom[x],x);
        myfind[x]=fa[x],x=a[j-1];
        for(int i=head[x];i;i=road[i].next){
            int v=road[i].to;
            Find(v);//更新后mi_sdom为v到x路径中sdom最小的点 
            if(sdom[mi_sdom[v]]==x)idom[v]=x;//v到sdom[v]路径中没有sdom>x的点,则idom[v]=sdom[v]=x; 
            else idom[v]=mi_sdom[v];//否则idom[v]=idom[mi_sdom[v]](路径中sdom最小点的idom) 但idom[mi_sdom[v]]可能还没求出来,所以先记录一下 
        }
    }
    for(int i=2;i<=si;i++){
        int x=a[i];
        if(idom[x]!=sdom[x])idom[x]=idom[idom[x]];//将idom[v]=idom[mi_sdom[v]]没完成的步骤不上 
    }
}
int main(){
    int u,v;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d",&u,&v),add_edge(u,v),add_edge_pr(v,u);
    }
    build();//build后idom就求出来了,然后根据题目进行计算
    return 0;
}

参考文献:http://blog.csdn.net/GEOTCBRL/article/details/57875070

http://blog.csdn.net/a710128/article/details/49913553

posted @ 2017-12-08 09:38  Bennettz  阅读(427)  评论(0编辑  收藏  举报