把牛的情况分成几个区块,各个区块里每头牛都是相互认为欢迎的,然后各个区块中如果出度为0的区块为1,那么有解且解为出度为0的区块里的牛的个数,反之无解。
区块用tarjan求得。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
const int N=10005;
int dfn[N], low[N], stk[N], id[N], out[N];
int stop, Dindex, Bcnt, n, m;
bool inq[N];
vector<int>eg[N];
void tarjan(int u)
{
int i, v;
dfn[u]=low[u]=++Dindex;
inq[u]=1;
stk[++stop]=u;
for(i=0;i<eg[u].size();i++){
v=eg[u][i];
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(inq[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
Bcnt++;
do
{
v=stk[stop--];
id[v]=Bcnt;
inq[v]=0;
}while(u!=v);
}
}
int main()
{
int i, j, st, ed, v;
while(~scanf("%d%d",&n,&m)){
for(i=1;i<=n;i++) eg[i].clear();
for(i=1;i<=m;i++){
scanf("%d%d",&st,&ed);
eg[st].push_back(ed);
}
Bcnt=Dindex=stop=0;
memset(dfn,0,sizeof(dfn));
memset(inq,0,sizeof(inq));
for(i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
memset(out,0,sizeof(out));
for(i=1;i<=n;i++){
for(j=0;j<eg[i].size();j++){
v=eg[i][j];
if(id[v]!=id[i])
out[id[i]]++;
}
}
int sum=0;
for(i=1;i<=Bcnt;i++)
if(out[i]==0)
sum++;
if(sum==1){
int ans=0;
for(i=1;i<=n;i++)
if(out[id[i]]==0)
ans++;
printf("%d\n",ans);
}
else puts("0");
}
return 0;
}