• 支配树


    推荐博客:

    https://www.cnblogs.com/fenghaoran/p/dominator_tree.html

    https://blog.csdn.net/litble/article/details/83019578

    模板:

    luogu5180

    传送:https://www.luogu.org/problem/P5180

    题意:给定一张有向图,求从1号点出发,每个点能支配的点的个数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=3e5+10;
     4 int n,m,num,dfn[N],fa[N],pos[N],f[N],mi[N],sdom[N],idom[N],size[N]; 
     5 struct node{
     6     int to,nxt;
     7 };
     8 struct Graph{
     9     node edge[N<<1];
    10     int head[N],tot;
    11     void clear(){
    12         tot=0;
    13         for (int i=0;i<=n;i++) head[i]=-1;
    14     }
    15     void link(int x,int y){
    16         edge[++tot]={y,head[x]};head[x]=tot;
    17     }
    18 }g,rg,ng,tr;
    19 void init(){
    20     num=0;g.clear(),rg.clear(),ng.clear(),tr.clear();
    21     for(int i=1;i<=n;++i)
    22         pos[i]=dfn[i]=idom[i]=fa[i]=size[i]=0,mi[i]=sdom[i]=f[i]=i;
    23 }
    24 void tarjan(int x){
    25     dfn[x]=++num; pos[num]=x;
    26     for (int i=g.head[x];i!=-1;i=g.edge[i].nxt){
    27         int u=g.edge[i].to;
    28         if (dfn[u]) continue;
    29         fa[u]=x;
    30         tarjan(u);
    31     }
    32 }
    33 int find(int x){
    34     if (x==f[x]) return x;
    35     int tmp=f[x]; f[x]=find(f[x]);
    36     if (dfn[sdom[mi[tmp]]]<dfn[sdom[mi[x]]]) mi[x]=mi[tmp];
    37     return f[x];
    38 }
    39 void work(){
    40     for (int i=n;i>1;i--){
    41         int x=pos[i],tmp=n;
    42         for (int j=rg.head[x];j!=-1;j=rg.edge[j].nxt){
    43             int u=rg.edge[j].to;
    44             if (!dfn[u]) continue;
    45             if (dfn[u]<dfn[x]) tmp=min(tmp,dfn[u]);
    46             else{
    47                 find(u);
    48                 tmp=min(tmp,dfn[sdom[mi[u]]]);
    49             }
    50         }
    51         sdom[x]=pos[tmp]; f[x]=fa[x];
    52         ng.link(sdom[x],x);
    53         x=pos[i-1];
    54         for (int j=ng.head[x];j!=-1;j=ng.edge[j].nxt){
    55             int u=ng.edge[j].to;
    56             find(u);
    57             if (sdom[mi[u]]==sdom[u]) idom[u]=sdom[u];
    58             else idom[u]=mi[u];
    59         }
    60     }
    61     for (int i=2;i<=n;i++){
    62         int x=pos[i];
    63         if (idom[x]!=sdom[x]) idom[x]=idom[idom[x]];
    64         tr.link(idom[x],x);
    65     }
    66 }
    67 void calc(int x){
    68     size[x]=1;
    69     for (int i=tr.head[x];i!=-1;i=tr.edge[i].nxt){
    70         int u=tr.edge[i].to;
    71         calc(u);
    72         size[x]+=size[u];
    73     }
    74 } 
    75 void solve(){
    76     tarjan(1);work();
    77     calc(1); 
    78     for (int i=1;i<=n;i++)
    79         if (i<n) printf("%d ",size[i]);
    80         else printf("%d
    ",size[i]);
    81 }
    82 
    83 int main(){
    84     int x,y;
    85     scanf("%d%d",&n,&m);
    86     init();
    87     for (int i=0;i<m;i++){
    88         scanf("%d%d",&x,&y);
    89         g.link(x,y); rg.link(y,x);
    90     }
    91     solve();
    92     return 0;
    93 } 
    View Code

    练习:

    1.hdoj4694

    传送:http://acm.hdu.edu.cn/showproblem.php?pid=4694

    题意:从$n$点开始传送信息,问每一个点获得信息所必须经过的点的编号和为多少。

    分析:是在有向图里找到关键点。考虑构建支配树,然后求解答案。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=5e4+10;
     4 const int M=1e5+10;
     5 int n,m,num,dfn[N],fa[N],pos[N],f[N],mi[N],sdom[N],idom[N],size[N]; 
     6 struct node{
     7     int to,nxt;
     8 };
     9 struct Graph{
    10     node edge[M];
    11     int head[N],tot;
    12     void clear(){
    13         tot=0;
    14         for (int i=0;i<=n;i++) head[i]=-1;
    15     }
    16     void link(int x,int y){
    17         edge[++tot]={y,head[x]};head[x]=tot;
    18     }
    19 }g,rg,ng,tr;
    20 void init(){
    21     num=0;g.clear(),rg.clear(),ng.clear(),tr.clear();
    22     for(int i=1;i<=n;++i)
    23         pos[i]=dfn[i]=idom[i]=fa[i]=size[i]=0,mi[i]=sdom[i]=f[i]=i;
    24 }
    25 void tarjan(int x){
    26     dfn[x]=++num; pos[num]=x;
    27     for (int i=g.head[x];i!=-1;i=g.edge[i].nxt){
    28         int u=g.edge[i].to;
    29         if (dfn[u]) continue;
    30         fa[u]=x;
    31         tarjan(u);
    32     }
    33 }
    34 int find(int x){
    35     if (x==f[x]) return x;
    36     int tmp=f[x]; f[x]=find(f[x]);
    37     if (dfn[sdom[mi[tmp]]]<dfn[sdom[mi[x]]]) mi[x]=mi[tmp];
    38     return f[x];
    39 }
    40 void work(){
    41     for (int i=n;i>1;i--){
    42         int x=pos[i],tmp=n;
    43         for (int j=rg.head[x];j!=-1;j=rg.edge[j].nxt){
    44             int u=rg.edge[j].to;
    45             if (!dfn[u]) continue;
    46             if (dfn[u]<dfn[x]) tmp=min(tmp,dfn[u]);
    47             else{
    48                 find(u);
    49                 tmp=min(tmp,dfn[sdom[mi[u]]]);
    50             }
    51         }
    52         sdom[x]=pos[tmp]; f[x]=fa[x];
    53         ng.link(sdom[x],x);
    54         x=pos[i-1];
    55         for (int j=ng.head[x];j!=-1;j=ng.edge[j].nxt){
    56             int u=ng.edge[j].to;
    57             find(u);
    58             if (sdom[mi[u]]==sdom[u]) idom[u]=sdom[u];
    59             else idom[u]=mi[u];
    60         }
    61     }
    62     for (int i=2;i<=n;i++){
    63         int x=pos[i];
    64         if (idom[x]!=sdom[x]) idom[x]=idom[idom[x]];
    65         tr.link(idom[x],x);
    66     }
    67 }
    68 void calc(int x,int sum){
    69     size[x]=sum+x;
    70     for (int i=tr.head[x];i!=-1;i=tr.edge[i].nxt){
    71         int u=tr.edge[i].to;
    72         calc(u,sum+x);
    73     }
    74 } 
    75 void solve(){
    76     tarjan(n);work();
    77     calc(n,0); 
    78     for (int i=1;i<=n;i++)
    79         if (i<n) printf("%d ",size[i]);
    80         else printf("%d
    ",size[i]);
    81 }
    82 
    83 int main(){
    84     int x,y;
    85     while (~scanf("%d%d",&n,&m)){
    86         init();
    87         for (int i=0;i<m;i++){
    88             scanf("%d%d",&x,&y);
    89             g.link(x,y); rg.link(y,x);
    90         }
    91         solve();
    92     };
    93     return 0;
    94 } 
    hdoj4694
  • 相关阅读:
    Django中前端界面实现级联查询
    二叉树遍历规则
    计算机组成原理面试总结
    用python介绍4种常用的单链表翻转的方法
    跨域资源共享(CORS)
    python中单例模式的四种实现方式
    算法和数据结构
    手写配置文件实现两套配置文件的切换
    CentOS 7 安装教程
    配置管理系统
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/11280072.html
Copyright © 2020-2023  润新知