首先我们要理解题意(一开始没想清楚) 后面才想明白
以下3点很重要!!!
1,如果明星牛羡慕其它牛,那么被它羡慕的牛也一定会羡慕它,然后构成一个环,所以我们可以考虑tarjan缩点
2,缩点以后出度为0的即为明星牛,反之出度不为0的肯定不是明星牛,因为to[x]不羡慕x
3,如果缩点后不止一个点出度为0的话就没有明星牛,因为这n个出度为0的点不能相互羡慕
搞懂了以上三点思路就清晰了
tarjan缩点,tarjan的过程中要记下一个缩掉的环中点的个数
最后有明星牛就输出个数,没有就输出0
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <stack>
#define maxn 100001
using namespace std;
int n,m,next[maxn],to[maxn],st[maxn],low[maxn],dfn[maxn],scc[maxn],out[maxn],topt,num,ans,nn[maxn];
bool f[maxn];
void add(int x,int y)
{
to[++topt]=y;
next[topt]=st[x];
st[x]=topt;
}
stack<int>s;
void tarjan(int x)
{
dfn[x]=low[x]=++topt;
f[x]=1; s.push(x); int p=st[x];
while (p)
{
if (!dfn[to[p]]) {tarjan(to[p]); low[x]=min(low[x],low[to[p]]);}
else if (f[to[p]]) low[x]=min(low[x],dfn[to[p]]);
p=next[p];
}
if (dfn[x]==low[x])
{
num++;
while (s.top()!=x)
{
f[s.top()]=1;
scc[s.top()]=num;
s.pop();
nn[num]++;
}
f[s.top()]=1;
scc[s.top()]=num;
s.pop();
nn[num]++;
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {int xx,yy; scanf("%d%d",&xx,&yy); add(xx,yy);}
topt=0;
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
{
int p=st[i];
while (p)
{
if (scc[i]!=scc[to[p]]) out[scc[i]]++;
p=next[p];
}
}
int judge=0;
for (int i=1;i<=num;i++)if (out[i]==0) judge++,ans=nn[i];
if (judge!=1) printf("0");else printf("%d",ans);
return 0;
}