题目背景
本题测试数据已修复。
题目描述
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶
牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果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
Tarjan算法,倒序建边,这样会提高效率。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int Q=10005;
const int N=50005;
int to[N],nex[N],fir[Q];
int ccc,num,dfn[Q],low[Q],d[Q],s1[Q];
int tot=0,ch[Q],n,m;
int top,s2[Q];
inline void add(int x,int y){
to[++tot]=y;
nex[tot]=fir[x];
fir[x]=tot;
}
void Tarjan(int u){
dfn[u]=low[u]=++num;
s2[++top]=u;
for(int i=fir[u];i;i=nex[i]){
int v=to[i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else{
if(!ch[v]){
low[u]=min(low[u],dfn[v]);
}
}
}
if(low[u]==dfn[u]){
ch[u]=++ccc;
++s1[ccc];
while(s2[top]!=u){
++s1[ccc];
ch[s2[top]]=ccc;
--top;
}
--top;
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
add(y,x);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
Tarjan(i);
}
}
for(int i=1;i<=n;i++){
for(int j=fir[i];j;j=nex[j]){
if(ch[i]!=ch[to[j]]){
d[ch[to[j]]]++;
}
}
}
int ans=0,u=0;
for(int i=1;i<=ccc;i++){
if(!d[i]){
ans=s1[i];
u++;
}
}
if(u==1){
printf("%d\n",ans);
}
else{
printf("0\n");
}
return 0;
}