坐井观天

In the name of dream

导航

POJ 2186 Tarjan缩点构图+处理度数

Posted on 2012-04-18 18:32  一毛_  阅读(210)  评论(0)    收藏  举报

题目链接: http://poj.org/problem?id=2186

题目大意:

  给定一个n,m( 1<=n<=10000, 0<=m<=50000 )代表n头牛,m个关系,然后是m行,每行一个u,v代表 牛u认为牛v是popular的, 问有多少头牛被其他所有牛认为是popular的;

分析:

  Tarjan缩点后,dfs扫描处理出每个强连通分量(SCC)的度数即可,关键是结论。

  这题的答案应该是出度 out[i] == 0 的SCC的个数必须为1。  

  (开始我考虑好多情况,唯一漏掉的情况在我下载USACO的数据后被我发现了;)

代码:

POJ 2186
  1 /*2186    Accepted    728K    79MS    C++    2618B    2012-04-18 19:09:52*/
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <vector>
  8 using namespace std;
  9 
 10 #define mpair make_pair
 11 #define pii pair<int,int>
 12 #define MM(a,b) memset(a,b,sizeof(a));
 13 typedef long long lld;
 14 typedef unsigned long long u64;
 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
 17 #define maxn 10020
 18 
 19 int n,m,top;
 20 struct Edge{
 21     int v;
 22     Edge *next;
 23 } *adj[maxn], edge[50010];
 24 void Addedge(int u,int v){
 25     Edge *p= &edge[++top];
 26     p->v= v;
 27     p->next= adj[u];
 28     adj[u]= p;
 29 }
 30 
 31 int Bcnt, Top, Index;
 32 int c[maxn], belong[maxn];
 33 int stack[maxn], dfn[maxn], low[maxn];
 34 bool instack[maxn];
 35 
 36 void Tarjan(int u){
 37     instack[u]= 1;
 38     stack[++Top]= u;
 39     dfn[u]= low[u]= ++Index;
 40     for(Edge *p= adj[u];p;p= p->next){
 41         int v= p->v;
 42         if( !dfn[v] ){
 43             Tarjan( v );
 44             up_min( low[u], low[v] );
 45         }
 46         else if( instack[v] )
 47             up_min( low[u], dfn[v] );
 48     }
 49     if( low[u]==dfn[u] ){
 50         Bcnt++;
 51         c[Bcnt]= 0; /// Init;
 52         int v;
 53         do{
 54             v= stack[Top--];
 55             instack[v]= 0;
 56             belong[v]= Bcnt;
 57             c[Bcnt]++;
 58         }while( u!=v );
 59     }
 60 }
 61 
 62 bool vis[maxn];
 63 int out[maxn];
 64 void dfs(int u){
 65     vis[u]= 1;
 66     for(Edge *p= adj[u];p;p= p->next){
 67         int v= p->v;
 68         if( belong[v] != belong[u] ){
 69             out[ belong[u] ]++;
 70         }
 71         if( !vis[v] )
 72             dfs( v );
 73     }
 74 }
 75 
 76 int main()
 77 {
 78     while(scanf("%d%d", &n, &m)!=EOF){
 79         top= 0;
 80         MM( adj, 0 );
 81         int i, u, v;
 82         for(i=1;i<=m;++i){
 83             scanf("%d%d", &u, &v);
 84             Addedge( u, v );
 85         }
 86         if( 1==n ){
 87             puts("0");
 88             continue;
 89         }
 90 
 91         Bcnt= Top= Index= 0;
 92         for(i=1;i<=n;++i) dfn[i]= low[i]= instack[i]= 0;
 93         for(i=1;i<=n;++i){
 94             if( !dfn[i] )
 95                 Tarjan( i );
 96         }
 97 
 98         if( Bcnt==1 ) printf("%d\n", n);
 99         else{
100             fill( out+1, out+1+Bcnt, 0 );
101             fill( vis+1, vis+1+n, 0 );
102             for(i=1;i<=n;++i)
103                 if( !vis[i] )
104                     dfs( i );
105 
106             int c2=0, t;
107             for(i=1;i<=Bcnt;++i)
108                 if( out[i]==0 ){
109                     c2++; t=i;
110                 }
111             if( c2==1 ) printf("%d\n", c[t]);
112             else puts("0");
113         }
114     }
115 }