Poj 2186 Popular Cows(強連通成分)

13934 ワード

http://poj.org/problem?id=2186
tarjanで強い連通成分の個数を算出してその縮点を1本の木につなげると問題で求めたものが求出度0になるそのノードは木の中で唯一の木の根である

  1 #include <iostream>

  2  #include<cstdio>

  3  #include<cstring>

  4  #include<algorithm>

  5  #include<stdlib.h>

  6  #include<stack>

  7  using namespace std;

  8  #define M 50010

  9  #define N 10010

 10  struct node

 11  {

 12      int u,v,next;

 13  }edge[M*2];

 14  int head[N],lowlink[N],pre[N],t,sccno[N],scc,dep,dout[N];

 15  stack<int>s;

 16  void init()

 17  {

 18      t = 0;

 19      memset(head,-1,sizeof(head));

 20      memset(lowlink,0,sizeof(lowlink));

 21      memset(pre,0,sizeof(pre));

 22      memset(sccno,0,sizeof(sccno));

 23      dep=0;scc=0;

 24  }

 25  void add(int u,int v)

 26  {

 27      edge[t].u = v;

 28      edge[t].v = v;

 29      edge[t].next = head[u];

 30      head[u] = t++;

 31  }

 32  void dfs(int u)

 33  {

 34      lowlink[u] = pre[u] = ++dep;

 35      s.push(u);

 36      for(int i = head[u] ; i != -1 ; i = edge[i].next)

 37      {

 38          int v = edge[i].v;

 39          if(!pre[v])

 40          {

 41              dfs(v);

 42              lowlink[u] = min(lowlink[u],lowlink[v]);

 43          }

 44          else if(!sccno[v])

 45          lowlink[u] = min(lowlink[u],pre[v]);

 46      }

 47      if(lowlink[u]==pre[u])

 48      {

 49          scc++;

 50          for(;;)

 51          {

 52              int x = s.top();s.pop();

 53              sccno[x] = scc;

 54              if(x==u) break;

 55          }

 56      }

 57  }

 58  void find_scc(int n)

 59  {

 60      for(int i = 1 ; i <= n  ; i++)

 61      if(!pre[i]) dfs(i);

 62  }

 63  int main()

 64  {

 65      int i,j,n,m,a,b;

 66      while(cin>>n>>m)

 67      {

 68          init();

 69          while(m--)

 70          {

 71              cin>>a>>b;

 72              add(a,b);

 73          }

 74          find_scc(n);

 75          for(i = 1; i <= scc ; i++)

 76          dout[i] = 0;

 77          for(i = 1; i <= n ; i++)

 78              for(j = head[i] ; j!=-1 ; j = edge[j].next)

 79              {

 80                  int v = edge[j].v;

 81                  if(sccno[i]!=sccno[v])

 82                      dout[sccno[i]] = 1;

 83              }

 84          int num=0,o,w=0;

 85          for(i = 1 ; i <= scc ; i++)

 86              if(dout[i]==0)

 87              {

 88                  o = i;

 89                  num++;

 90              }

 91          if(num==0)

 92          cout<<n<<endl;

 93          else if(num==1)

 94          {

 95              for(i = 1; i <= n ; i++)

 96              if(sccno[i]==o)

 97              {

 98                 w++;

 99              }

100              cout<<w<<endl;

101          }

102          else

103          cout<<"0
"; 104 } 105 return 0; 106 }

View Code