zoukankan      html  css  js  c++  java
  • poj 2186 "Popular Cows"(强连通分量入门题)

    传送门

    参考资料:

      [1]:挑战程序设计竞赛

    题意:

      每头牛都想成为牛群中的红人。

      给定N头牛的牛群和M个有序对(A, B),(A, B)表示牛A认为牛B是红人;

      该关系具有传递性,所以如果牛A认为牛B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人。

      不过,给定的有序对中可能包含(A, B)和(B, C),但不包含(A, C)。

      求被其他所有牛认为是红人的牛的总数。

    分析(摘抄自挑战程序设计竞赛):

      考虑以牛为顶点的有向图,对每个有序对(A, B)连一条从 A到B的有向边;

      那么,被其他所有牛认为是红人的牛对应的顶点,也就是从其他所有顶点都可达的顶点。

      虽然这可以通过从每个顶点出发搜索求得,但总的复杂度却是O(NM),是不可行的,必须要考虑更为高效的算法。

      假设有两头牛A和B都被其他所有牛认为是红人,那么显然,A被B认为是红人,B也被A认为是红人;

      即存在一个包含A、B两个顶点的圈,或者说,A、B同属于一个强连通分量。

      反之,如果一头牛被其他所有牛认为是红人,那么其所属的强连通分量内的所有牛都被其他所有牛认为是红人。

      由此,我们把图进行强连通分量分解后,至多有一个强连通分量满足题目的条件。

      而按前面介绍的算法进行强连通分量分解时,我们还能够得到各个强连通分量拓扑排序后的顺序;

      唯一可能成为解的只有拓扑序最后的强连通分量。

      所以在最后,我们只要检查这个强连通分量是否从所有顶点可达就好了。

      该算法的复杂度为O(N+M),足以在时限内解决原题。

    对红色字体的理解:

      满足条件的强连通分量的特点是(红牛所在的强连通分量):

        (1)出度为0

        (2)其余的节点都会间接或直接的指向此强连通分量的任一节点

      再结合向量vs 的作用,在Dfs( )中,vs中存储的第一个节点肯定是满足条件的强连通分量中的某一节点;

      在vs中,越靠前的节点的拓扑序越大。

    AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 using namespace std;
      6 #define mem(a,b) memset(a,b,sizeof(a))
      7 const int maxn=1e5+50;
      8 
      9 int n,m;
     10 int num;
     11 int head[maxn];
     12 struct Edge
     13 {
     14     int to;
     15     int next;
     16 }G[10*maxn];
     17 void addEdge(int u,int v)
     18 {
     19     G[num]={v,head[u]};
     20     head[u]=num++;
     21 }
     22 struct SCC
     23 {
     24     int col[maxn];
     25     bool vis[maxn];
     26     vector<int >vs;
     27     void DFS(int u)
     28     {
     29         vis[u]=true;
     30         for(int i=head[u];~i;i=G[i].next)
     31         {
     32             int v=G[i].to;
     33             if((i&1) || vis[v])//正向边,num为偶数
     34                 continue;
     35             DFS(v);
     36         }
     37         vs.push_back(u);
     38     }
     39     void RDFS(int u,int k)
     40     {
     41         vis[u]=true;
     42         col[u]=k;
     43         for(int i=head[u];~i;i=G[i].next)
     44         {
     45             int v=G[i].to;
     46             if(!(i&1) || vis[v])//反向边,num为奇数
     47                 continue;
     48             RDFS(v,k);
     49         }
     50     }
     51     int scc()
     52     {
     53         vs.clear();
     54         mem(vis,false);
     55         for(int i=1;i <= n;++i)
     56             if(!vis[i])
     57                 DFS(i);
     58 
     59         int k=0;
     60         mem(vis,false);
     61         for(int i=vs.size()-1;i >= 0;--i)//从拓扑序的最大值开始查找SCC
     62             if(!vis[vs[i]])
     63                 RDFS(vs[i],++k);
     64         return k;
     65     }
     66 }_scc;
     67 int Solve()
     68 {
     69     int k=_scc.scc();
     70     int ans=0;
     71     int u;
     72     for(int i=1;i <= n;++i)
     73         if(_scc.col[i] == k)
     74         {
     75             ans++;
     76             u=i;
     77         }
     78     mem(_scc.vis,false);
     79     _scc.RDFS(u,0);//再次调用RDFS()判断u是否可以到达其他任意节点
     80     for(int i=1;i <= n;++i)
     81         if(!_scc.vis[i])
     82             return 0;
     83     return ans;
     84 }
     85 void Init()
     86 {
     87     num=0;
     88     mem(head,-1);
     89 }
     90 int main()
     91 {
     92     while(~scanf("%d%d",&n,&m))
     93     {
     94         Init();
     95         for(int i=1;i <= m;++i)
     96         {
     97             int u,v;
     98             scanf("%d%d",&u,&v);
     99             addEdge(u,v);
    100             addEdge(v,u);
    101         }
    102         printf("%d
    ",Solve());
    103     }
    104     return 0;
    105 }
    View Code
  • 相关阅读:
    Asp.Net Core 程序部署到Linux(centos)生产环境(二):docker部署
    ASP.NET Core Docker部署
    将.NET Core部署在Docker
    linux 常用命令
    Wpf(Storyboard)动画简单实例
    uwp之图片旋转动画实现
    2011年度十大杰出IT博客获奖感言
    将BT下载对抗到底
    P3271 [JLOI2016]方 容斥+数学
    GCD is Funny
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9740737.html
Copyright © 2011-2022 走看看