Popular Cows
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 40223 | Accepted: 16381 |
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.
题意:
给你n头牛,m条关系。每条关系里有两个数x y表示牛x崇拜牛y。现在问你,有多少牛会被其他所有的牛崇拜。
做法:
先用强连通分量进行缩点,缩点后的一个分量代表这一块中的奶牛之间都是互相崇拜,再判断这个分量和其他分量之间的关系。如果存在有且只有一个强连通分量的出度为0,则这个强连通分量里的奶牛都被其他奶牛崇拜。我们来验证一下,如果存在有且只有一个强连通分量的出度为0,表示这一块里的奶牛没有崇拜别人,其他分量中的奶牛一定会有崇拜这个分量中的奶牛,为什么呢?假设,当前联通块3没有入度也没有出度,联通块1崇拜联通块2,而因为只有块3的出度为0,并且要保证块3没有入度,所以块2必须有指向块1的一条边,这样的块1和块2是一个更大的强连通分量,而这个分量的出度为0,则假设不成立,所以原命题成立。因此只要判断是不是有且只有一个强连通分量的出度为0就好,有的话再看看这个强连通分量里有多少奶牛,输出即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
#include<vector>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=10005;
const int maxm=50005;
int n,m,head[maxn],now;
int belong[maxn],qiang,dfn[maxn],low[maxn],cnt;
int numqiang[maxn],out[maxn],fr[maxm],to[maxm],nex[maxm];
int sta[maxn],top;
vector<int> ve[maxn];
void add(int u,int v){
fr[now]=u,to[now]=v;
nex[now]=head[u]; head[u]=now++;
}
void tarjan(int x){
dfn[x]=low[x]=++cnt;
sta[++top]=x;
for(int i=head[x];~i;i=nex[i]){
int v=to[i];
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(!belong[v]) low[x]=min(low[x],low[v]);
}
if(dfn[x]==low[x]){
qiang++;
while(1){
int u=sta[top--];
belong[u]=qiang;
if(u==x) break;
}
}
}
int main(){
int x,y;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++){
int x=belong[i];
numqiang[x]++;
}
for(int i=0;i<now;i++){
int fx=belong[fr[i]],fy=belong[to[i]];
if(fx!=fy){
out[fx]++;
}
}
int ans=0,sum=0,aim;
for(int i=1;i<=qiang;i++){
if(!out[i]) {
sum++;
aim=i;
}
}
if(sum==1){
for(int i=1;i<=n;i++){
if(belong[i]==aim) ans++;
}
cout<<ans<<endl;
}
else cout<<"0"<<endl;
return 0;
}