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

 

转载于:https://www.cnblogs.com/TYH-TYH/p/9389751.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值