这题用的是Tarjan算法, 先求出强连通分量的个数, 如果为一, ans就是牛的个数, 如果不是, 求出出度为零的强连通分量的个数, 如果只有一个, 输出这个强连通分量里牛的个数, 如果不止一个, 输出0, 因为不存在牛被所有牛喜欢。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <stack>
#define mem(a) memset(a, 0, sizeof(a))
using namespace std;
int dfn[10005], low[10005], vis[10005], num[10005], jilu[10005], vis2[10005], w, n, m, flag, ans = 0;
stack<int> q;
struct node
{
int a;
node *next;
}point[10005];
void Tarjan(int s)
{
int i, t;
node *v;
q.push(s);
vis[s] = 1;
dfn[s] = low[s] = ++flag;
v = point[s].next;
while(v)
{
if(vis[v->a] == 0)
{
Tarjan(v->a);
low[s] = min(low[s], low[v->a]);
}
else
{
low[s] = min(low[s], dfn[v->a]);
}
v = v->next;
}
if(low[s] == dfn[s])
{
jilu[w] = s;
w++;
ans++;
do
{
t = q.top();
vis[t] = 2;
vis2[t] = s;
q.pop();
}while(s != t);
}
}
int main(int argc, char *argv[])
{
int i, j, k, a, b, o = 0, flag2, res, flag3;
scanf("%d%d",&n, &m);
flag = 0;
flag2 = 0;
flag3 = 0;
res = 0;
w = 0;
mem(dfn);
mem(low);
mem(vis);
mem(vis2);
mem(num);
mem(point);
for(i = 0;i < m;i++)
{
scanf("%d%d",&a, &b);
num[a]++;
node *p;
p = (node*)malloc(sizeof(node));
p->a = b;
p->next = point[a].next;
point[a].next = p;
}
for(i = 1;i <= n;i++)
{
if(vis[i] == 0)
{
flag = 0;
Tarjan(i);
}
}
if(ans == 1)
printf("%d\n", n);
else
{
for(i = 0;i < w;i++)
{
flag3 = 0;
for(j = 1;j <= n;j++)
{
if(vis2[j] == jilu[i])
{
node *p;
p = point[j].next;
while(p)
{
if(vis2[p->a] != jilu[i])
{
flag3 = 1;
}
p = p->next;
}
}
}
if(flag3 == 1)
o++;
else
flag2 = i;
}
if((ans - o) == 1)
{
for(i = 1;i <= n;i++)
{
if(vis2[i] == jilu[flag2])
res++;
}
printf("%d\n", res);
}
else
{
printf("0\n");
}
}
return 0;
}