题意:
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。
思路:
tarjan缩点后找出度为0的点,若有1个,则是明星,超过1个则没有明星。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e4 + 10;
int n, m, h[N], cnt, d[N], x[N], y[N];
int dfn[N], low[N], ins[N], scc[N], inde;
stack<int> s;
struct node {
int v, net;
} no[N];
void add(int u, int v) {
no[cnt].v = v;
no[cnt].net = h[u];
h[u] = cnt++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++inde;
s.push(u);
ins[u] = 1;
for(int i = h[u]; ~i; i = no[i].net) {
int v = no[i].v;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(ins[v])
low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]) {
while(s.top() != u) {
int v = s.top();
ins[v] = 0, scc[v] = u;
s.pop();
}
ins[u] = 0, scc[u] = u;
s.pop();
}
}
int main() {
memset(h, -1, sizeof h);
cin >> n >> m;
for(int i = 0; i < m; i++) {
cin >> x[i] >> y[i];
add(x[i], y[i]);
}
for(int i = 1; i <= n; i++)
if(!dfn[i])
tarjan(i);
int ans = 0, ru = 0, root = -1;
for(int i = 1; i <= n; i++)
for(int j = h[i]; ~j; j = no[j].net) {
int v = no[j].v;
if(scc[i] != scc[v]) {
d[scc[i]]++;//统计出度
}
}
for(int i = 1; i <= n; i++)
if(d[scc[i]] == 0 && root != scc[i])//防止同一个强连通分量的重复统计
ru++, root = scc[i];//记录出度为0的个数
if(ru > 1) {
cout << 0;
return 0;
}
for(int i = 1; i <= n; i++)
if(scc[i] == root)//计算强连通分量有多少牛
ans++;
cout << ans;
return 0;
}