如果是一个拓扑图,存在最受欢迎的牛 等价于 只有一个出度为0的节点。
如果不是一个拓扑图,需要使用tarjan算法进行缩点,最后符合条件的点的强连通分量即使答案。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int stk[N], top;
int e[N], ne[N], h[N], idx;
int dfn[N], low[N], id[N], ins[N], Time, cnt;
int dout[N];
vector<int> scc[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++Time;
stk[++top] = x, ins[x] = 1;
for(int i = h[x]; ~i; i = ne[i]) {
int j = e[i];
if(!dfn[j]) {
tarjan(j);
low[x] = min(low[x], low[j]);
}else if(ins[j]) {
low[x] = min(low[x], dfn[j]);
}
}
if(low[x] == dfn[x]) {
int y;
cnt++;
do{
y = stk[top--];
ins[y] = 0;
id[y] = cnt;
scc[cnt].push_back(y);
}while(x!=y);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
memset(h, -1, sizeof(h));
while(m--)
{
int u, v;
cin >> u >> v;
add(u,v);
}
for(int i = 1; i <= n; i++) {
if(!dfn[i]) {
tarjan(i);
}
}
for(int i = 1; i <= n; i++) {
for(int j = h[i]; ~j; j = ne[j]) {
int k = e[j];
int a = id[i], b = id[k];
if(a!=b) dout[a]++;
}
}
int zero = 0, sum = 0;
for(int i = 1; i <= cnt; i++) {
if(!dout[i]) {
zero++;
sum += scc[i].size();
if(zero>1) {
sum = 0;
break;
}
}
}
cout << sum;
return 0;
}