题目链接:https://www.luogu.com.cn/problem/P2341
本题就是要求强连通分量,那么何为强连通分量?言简意赅地说就是在一个有向图中所有点可以互相可达。在一个强连通分量中,所有牛都是互相喜欢的。我们可以用tarjan来求强连通分量,把一个强连通分量的点全部染成一个颜色,如果一个强连通分量的出度为0,这个强连通分量的牛就可能是明星奶牛,但如果有两个强连通分量的出度为0,那就不可能有明星奶牛。因为如果这种情况出现的话,就肯定所有奶牛不被至少一个奶牛崇拜,所以不可能有明星奶牛。
代码如下
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
const int maxm=5e4+5;
struct node
{
int to,next;
}p[maxm];
int dfn[maxn],low[maxn],stc[maxn];
int col[maxn],col_num[maxn],head[maxn];
int outdeg[maxn];
bool vis[maxn];
int top,cnt,dfn_num,col_id;
void add(int x,int y)
{
p[++cnt].next=head[x];
p[cnt].to=y;
head[x]=cnt;
}
void tarjan(int u)
{
stc[++top]=u;
vis[u]=1;
dfn[u]=low[u]=++dfn_num;
for(int i=head[u];i;i=p[i].next)
{
int v=p[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
vis[u]=false;
col[u]=++col_id;
int len=1;
while(stc[top]!=u)
{
len++;
vis[stc[top]]=false;
col[stc[top--]]=col_id;
}
col_num[col_id]=len;
top--;
}
}
int n,m;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
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++)
for(int j=head[i];j;j=p[j].next)
{
int v=p[j].to;
if(col[v]!=col[i])//不是一个强连通分量
outdeg[col[i]]++;
}
int ans=0;
for(int i=1;i<=col_id;i++)
if(!outdeg[i])
{
if(ans)//两个出度为0,没有明星奶牛
{
puts("0");
return 0;
}
else
ans=col_num[i];
}
printf("%d\n",ans);
return 0;
}