zoukankan      html  css  js  c++  java
  • 图论:强连通分量-缩点重构图

    POJ2186:利用Tarjan强连通分量求缩点重构图

    缩点就是在求出图的所有的强连通分量之后

    把强连通分量都看成一个点

    这样形成的一个新的图叫做缩点重构图

    下面描述一下POJ2186的题意:

    给出n个点和m条边(点与点之间的关系),关系具有传递性,问最后有多少点满足其他所有点都能够通达到此

    首先我们求出原图的强连通分量

    然后将所有的强连通分量缩成点

    这样形成的缩点重构图就是一个DAG

    DAG中,至少有一个以上的点的出度为0(否则会成环)

    然后我们统计出度为0的点的数量

    如果这种点的数量大于等于2,那么说明这些点(其实是强连通分量缩成的超级点)之间没有关系,答案为0

    如果这种点只有一个,那么这个点所对应的强连通分量中的真实点数就是答案

    然后我们看一下做法:

    int n,m,cnt,top,sum,deep,ans,tmp1;
    int g[maxn],dfn[maxn],low[maxn],vis[maxn],st[maxn],col[maxn],deg[maxn],tot[maxn];
    struct Edge{int t,next;}e[maxm];

    这里面tmp1就是用来记录强连通分量缩成的点中,出度为0的点的数量的

    我们重点看一下缩点的过程:

            for(u=1;u<=n;u++)
            {
                for(int tmp=g[u];tmp;tmp=e[tmp].next)
                {
                    v=e[tmp].t;
                    if(col[v]!=col[u]) deg[col[u]]++;
                }
                tot[col[u]]++;    
            }
            for(int i=1;i<=sum;i++)
                if(deg[i]==0) {tmp1++;ans=tot[i];}

    首先找出所有超级点的出度

    并记录一下这些强连通分量所包含的点的数量

    最后根据超级点的出度统计答案就好了

    下面给出完整的实现:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=10005;
     6 const int maxm=50005;
     7 int n,m,cnt,top,sum,deep,ans,tmp1;
     8 int g[maxn],dfn[maxn],low[maxn],vis[maxn],st[maxn],col[maxn],deg[maxn],tot[maxn];
     9 struct Edge{int t,next;}e[maxm];
    10 void addedge(int u,int v)
    11 {
    12     e[++cnt].t=v;
    13     e[cnt].next=g[u];g[u]=cnt;
    14 }
    15 void tarjan(int u)
    16 {
    17     dfn[u]=low[u]=++deep;
    18     vis[u]=1;st[++top]=u;
    19     for(int tmp=g[u];tmp;tmp=e[tmp].next)
    20     {
    21         int v=e[tmp].t;
    22         if(!dfn[v]) {tarjan(v);low[u]=min(low[u],low[v]);}
    23         else if(vis[v]) low[u]=min(low[u],low[v]);
    24     }
    25     if(dfn[u]==low[u])
    26     {
    27         col[u]=++sum;
    28         vis[u]=0;
    29         while(st[top]!=u)
    30         {
    31             col[st[top]]=sum;
    32             vis[col[top--]]=0;
    33         }
    34         top--;
    35     }
    36 }
    37 int main()
    38 {
    39     int u,v;
    40     while(scanf("%d%d",&n,&m)!=EOF)
    41     {
    42         memset(vis,0,sizeof(vis));
    43         memset(deg,0,sizeof(deg));
    44         memset(dfn,0,sizeof(dfn));
    45         memset(tot,0,sizeof(tot));
    46         memset(col,0,sizeof(col));
    47         memset(st,0,sizeof(st));
    48         memset(g,0,sizeof(g));
    49         memset(e,0,sizeof(e));
    50         for(int i=1;i<=m;i++)
    51             scanf("%d%d",&u,&v),addedge(u,v);
    52         for(int i=1;i<=n;i++)
    53             if(!dfn[i]) tarjan(i);
    54         for(u=1;u<=n;u++)
    55         {
    56             for(int tmp=g[u];tmp;tmp=e[tmp].next)
    57             {
    58                 v=e[tmp].t;
    59                 if(col[v]!=col[u]) deg[col[u]]++;
    60             }
    61             tot[col[u]]++;    
    62         }
    63         for(int i=1;i<=sum;i++)
    64             if(deg[i]==0) {tmp1++;ans=tot[i];}
    65         if(tmp1==0) printf("0
    ");
    66         else
    67         {
    68             if(tmp1>1) printf("0
    ");
    69             else printf("%d
    ",ans);
    70         }
    71     }
    72     return 0;
    73 }
  • 相关阅读:
    js_css_dl.dt实现列表展开、折叠效果
    property_自己编写一个读取Property文件的Util类
    HttpClient_002_中文乱码、HttpClient中文乱码透析、总结
    HttpClient_001_初步实现项目01的servlet,与项目02的servlet,之间数据访问
    jsp:中文乱码解决
    linux命令
    js 监测from表单中的input和select,时时监测,没有输入或选择信息报错,不允许提交数据
    数据库的那些事
    待参考
    layer.open多次触发,遮罩层覆盖content的解决办法
  • 原文地址:https://www.cnblogs.com/aininot260/p/9429142.html
Copyright © 2011-2022 走看看