若A喜欢B则连一条边,求强联通分块,设出度为零的块数为C,若C>1则误解,C=1则输出块数
const int N = 10010, M = 50010;
struct Edge {
int v;
Edge *Next;
Edge() {}
Edge(int _v, Edge *_Next) : v(_v), Next(_Next) {}
} *Fir[N];
int n, m;
inline void Ins(int u, int v) {
Fir[u] = new Edge(v, Fir[u]);
}
inline void Input() {
scanf("%d%d", &n, &m);
For(i, 1, n) Fir[i] = NULL;
For(i, 1, m) {
int u, v;
scanf("%d%d", &u, &v), Ins(u, v);
}
}
int dfn[N], low[N], belong[N], tot, T;
bool Instack[N];
int Out[N];
stack<int> sta;
inline void tarjan(int x) {
dfn[x] = low[x] = ++T, sta.push(x), Instack[x] = 1;
for(Edge *Tab = Fir[x]; Tab != NULL; Tab = Tab->Next) {
int v = Tab->v;
if(dfn[v] == -1) {
tarjan(v);
low[x] = min(low[x], low[v]);
} else if(Instack[v]) low[x] = min(low[x], dfn[v]);
}
if(dfn[x] == low[x]) {
++tot;
while(sta.top() != x) {
int v = sta.top();
belong[v] = tot, sta.pop(), Instack[v] = 0;
}
belong[x] = tot, Instack[x] = 0, sta.pop();
}
}
inline void Solve() {
// rebuild
clr(dfn, 255), clr(Instack, 0), tot = T = 0;
while(sz(sta)) sta.pop();
For(i, 1, n)
if(dfn[i] == -1) tarjan(i);
// Check
For(i, 1, tot) Out[i] = 0;
For(i, 1, n)
for(Edge *Tab = Fir[i]; Tab != NULL; Tab = Tab->Next) {
int v = Tab->v;
if(belong[v] ^ belong[i]) {
Out[belong[i]] = 1;
break;
}
}
int Which = -1, Check = 0;
For(i, 1, tot)
if(!Out[i]) {
if(!Check) Which = i, Check = 1;
else if(Check) {
Which = -1;
break;
}
}
int Ans = 0;
For(i, 1, n) Ans += (belong[i] == Which);
printf("%d\n", Ans);
}
int main() {
#ifndef ONLINE_JUDGE
SETIO("1051");
#endif
Input();
Solve();
return 0;
}