题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜
欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你
算出有多少头奶牛可以当明星。
输入输出格式
输入格式:
第一行:两个用空格分开的整数:N和M
第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B
输出格式:
第一行:单独一个整数,表示明星奶牛的数量
输入输出样例
输入样例#1: 复制
3 3
1 2
2 1
2 3
输出样例#1: 复制
1
说明
只有 3 号奶牛可以做明星
【数据范围】
10%的数据N<=20, M<=50
30%的数据N<=1000,M<=20000
70%的数据N<=5000,M<=50000
100%的数据N<=10000,M<=50000
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100001;
int begin[maxn],next[maxn],to[maxn];
int tot,n,m;
int dfsn[maxn],low[maxn];
int stack_[maxn];
int num,cc[maxn],dis[maxn];
int put[maxn];
int flag[maxn];
void add_(int x,int y){
to[++tot]=y;
next[tot]=begin[x];
begin[x]=tot;
}
int find_(int x){
for(register int i=1;i<=stack_[0];++i)
if(stack_[i]==x)return true;
return false;
}
void tarjan(int u){
dfsn[u]=low[u]=++tot;
stack_[++stack_[0]]=u;
for(register int i=begin[u];i;i=next[i]){
int v=to[i];
if(!dfsn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(find_(v))low[u]=min(low[u],dfsn[v]);
}
if(low[u]==dfsn[u]){
++num;
cc[u]=num;
while(stack_[stack_[0]]!=u){
++dis[num];
cc[stack_[stack_[0]]]=num;
--stack_[0];
}
++dis[num];
cc[stack_[stack_[0]]]=num;
--stack_[0];
}
}
int main(){
scanf("%d %d",&n,&m);
register int i,j;
for(i=1;i<=m;++i){
int a,b;
scanf("%d %d",&b,&a);
add_(a,b);
}
for(i=1;i<=n;++i){
if(!dfsn[i])tarjan(i);
}
for(i=1;i<=n;++i)
for(j=begin[i];j;j=next[j])
if(cc[i]!=cc[to[j]])
++flag[cc[to[j]]];
int flag2=0;
for(i=1;i<=num;++i)
if(!flag[i])dis[0]=dis[i],++flag2;
if(flag2>=2)printf("0");
if(flag2==1)printf("%d",dis[0]);
return 0;
}