https://www.luogu.org/problemnew/show/P2341
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。
分析题意发现强连通分量中出度为0的点们可能是答案,如果出现两个或以上的出度为0的分量则不存在所有点都能到的点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
const int maxm = 5e4 + 10;
struct node {
int to, nxt;
node() {}
node(int _to, int _nxt) : to(_to), nxt(_nxt) {}
} E[maxm];
int top, head[maxn];
void addEdge(int u, int v) {
E[++top] = node(v, head[u]);
head[u] = top;
}
int dfn[maxn], tot, low[maxn], vis[maxn], clor, clr[maxn], cnt[maxn];
int out[maxn];
stack<int> stk;
void tarjan(int u) {
dfn[u] = low[u] = ++tot;
stk.push(u);
vis[u] = 1;
for (register int i = head[u]; i; i = E[i].nxt)
{
int v = E[i].to;
if(vis[v] == 0) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(vis[v] == 1)
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
int v;
clor++;
do {
v = stk.top();
stk.pop();
vis[v] = -1;
clr[v] = clor;
cnt[clor]++;
} while (v != u);
}
}
int main()
{
int n, m, a, b;
scanf("%d%d", &n, &m);
register int i;
for (i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
addEdge(a, b);
}
for (i = 1; i <= n; i++)
if(!dfn[i]) tarjan(i);
for (i = 1; i <= n; i++) {
for (register int x = head[i]; x; x = E[x].nxt) {
if(clr[i] == clr[E[x].to]) continue;
out[clr[i]]++;
}
}
int ans = 0;
for (i = 1; i <= clor; i++)
{
if(!out[i]) {
if(ans) {
printf("0\n");
return 0;
}
ans = i;
}
}
printf("%d\n", cnt[ans]);
// system("pause");
}