POJ 2168 Popular cows [Tarjan 缩点]

                                                                                                           Popular Cows
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 39115   Accepted: 15937

Description

Every cow's dream is to become the most popular cow in the herd. In a herd of N (1 <= N <= 10,000) cows, you are given up to M (1 <= M <= 50,000) ordered pairs of the form (A, B) that tell you that cow A thinks that cow B is popular. Since popularity is transitive, if A thinks B is popular and B thinks C is popular, then A will also think that C is
popular, even if this is not explicitly specified by an ordered pair in the input. Your task is to compute the number of cows that are considered popular by every other cow.

Input

* Line 1: Two space-separated integers, N and M

* Lines 2..1+M: Two space-separated numbers A and B, meaning that A thinks B is popular.

Output

* Line 1: A single integer that is the number of cows who are considered popular by every other cow.

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

Hint

Cow 3 is the only cow of high popularity.
 
Tarjan入门题,果然有的算法入门题就需要应用啊。。
求强连通分量的板子差不多找到个舒服的了,为了速度起见还是不用STL了吧。
这个题,问有没有点能被其他所有的点到达。强连通分量中是各自满足条件的
由于有向无环图中,出度为零的点是满足这个条件的。所以我们可以使用tarjan来找到所有的强连通分量,并进行缩点,对强连通分量进行编号,把每个点标记一下所属于的强连通分量,然后把图遍历一下,求出每个强连通分量的出度。
最后判断出度为0的强连通分量个数,若为1个,则存在,输出编号为这个的点个数即可。否则不存在。
  1   #include<cstdio>
  2   #include<cstring>
  3   #include<iostream>
  4   #include<cstdlib>
  5   #include<algorithm>
  6   #include<cmath>
  7   #include<vector>
  8   #include<stack>
  9   //#include<bits/stdc++.h>
 10   using namespace std;
 11   #define mem(a,b) memset(a,b,sizeof(a))
 12   #define ll long long
 13   #define inf 1000000000
 14   #define maxn 10005
 15   #define maxm 100005
 16   #define eps 1e-10
 17   #define for0(i,n) for(int i=1;i<=(n);++i)
 18   #define for1(i,n) for(int i=1;i<=(n);++i)
 19   #define for2(i,x,y) for(int i=(x);i<=(y);++i)
 20   #define for3(i,x,y) for(int i=(x);i>=(y);--i)
 21   #define mod 1000000007
 22   inline int read()
 23   {
 24       int x=0,f=1;char ch=getchar();
 25       while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
 26       while(ch>='0'&&ch<='9') {x=10*x+ch-'0';ch=getchar();}
 27       return x*f;
 28   }
 29   struct node{
 30     int to,next;
 31   }edge[maxm];
 32   int n,m,head[maxn],vis[maxn],dfn[maxn],low[maxn],du[maxn],num[maxn],cnt,timi,stack1[maxn],top,cut;
 33   void init()
 34   {
 35       memset(dfn,0,sizeof(dfn));
 36       memset(low,0,sizeof(low));
 37       memset(head,-1,sizeof(head));
 38       memset(vis,0,sizeof(vis));
 39       memset(num,0,sizeof(num));
 40       memset(du,0,sizeof(du));
 41       cnt=0;
 42       timi=1;
 43       top=0;
 44       cut=0;
 45   }
 46   stack <int> s;
 47   void addedge(int u,int v)
 48   {
 49       edge[cnt].to=v;
 50       edge[cnt].next=head[u];
 51       head[u]=cnt;
 52       cnt++;
 53   }
 54   void tarjan(int u)
 55   {
 56     dfn[u]=timi;
 57     low[u]=timi;
 58     timi++;
 59     s.push(u);
 60     //stack1[top]=u;top++;
 61     vis[u]=1;
 62     for(int i=head[u];i!=-1;i=edge[i].next)
 63     {
 64       int v=edge[i].to;
 65       if(!dfn[v]) {
 66         tarjan(v);
 67         low[u]=min(low[u],low[v]);
 68       }
 69       else{
 70         low[u]=min(low[u],dfn[v]);
 71       }
 72     }
 73       if(low[u]==dfn[u])
 74       {
 75         cut++;
 76         int x=s.top();
 77         while(!s.empty()&&x!=u)
 78         {
 79             vis[s.top()]=0;
 80             //vis[stack1[top]]=2;
 81             num[s.top()]=cut;
 82             s.pop();
 83             x=s.top();
 84         }
 85         num[s.top()]=cut;
 86         s.pop();
 87       }
 88     }
 89   int main()
 90   {
 91     int a,b;
 92     while(~scanf("%d%d",&n,&m))
 93     {
 94       init();
 95       for(int i=1;i<=m;++i)
 96         {scanf("%d%d",&a,&b);
 97           addedge(a,b);
 98           }
 99       for(int i=1;i<=n;++i)
100       {
101         if(!dfn[i]) tarjan(i); 
102       }
103       for(int i=1;i<=n;++i)
104       {
105         for(int j=head[i];j!=-1;j=edge[j].next)
106         {
107           if(num[i]!=num[edge[j].to]) {du[num[i]]++;
108           }
109         }
110       }
111       int sum=0,x;
112       for(int i=1;i<=cut;++i)
113       {
114         if(!du[i]) {sum++;x=i;}
115       }
116       if(sum==1)
117       {
118         sum=0;
119         for(int i=1;i<=n;++i) 
120             if(num[i]==x) sum++;
121         printf("%d\n",sum);
122       }
123       else puts("0\n");
124     }
125     return 0;
126   }
View Code

 

posted @ 2018-07-30 11:40  Maydaytyh  阅读(285)  评论(0编辑  收藏  举报