题目传送门sxazr
题目中奶牛之间的喜欢具有传递性,可以在有向图中找出强联通子图,每个子图中的奶牛都是相互喜欢的。
把每个强联通子图找出来,缩点,再看看有没有出度为0的点;如果出度为0的点大于等于2,那么就没有明星奶牛了。
如图,2和3两个点出度都为零,但2和3之间不喜欢;
上代码
#include <iostream>
#include <cstdio>
using namespace std;
int n,m,g,k[10001],st[10001],s[10001],top,hed[10001],net[50001],to[50001],dfn[10001],low[10001],num,co[10001],cnt;
void tarjan(int u)
{
low[u]=dfn[u]=++num;
st[++top]=u;
for(int i=hed[u];i;i=net[i]){
int v=to[i];
if(!dfn[v]){
sx(v);
low[u]=min(low[v],low[u]);
}
else if(!co[v]) low[u]=min(low[v],low[u]);
}
if(low[u]==dfn[u]){
co[u]=++cnt;s[cnt]++;
while(st[top]!=u) co[st[top--]]=cnt,s[cnt]++;
top--;
}
}
int main()
{
cin>>n>>m;
for(int a,b,i=1;i<=m;i++){
scanf("%d%d",&a,&b);
net[++g]=hed[a];hed[a]=g;to[g]=b;
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
for(int j=hed[i];j;j=net[j])
if(co[i]!=co[to[j]]) k[co[i]]++;
top=0;
for(int i=1;i<=cnt;i++)
if(k[i]==0) top++,g=s[i];
cout<<(top==1?g:0);
return 0;
}```