稍微学习一下强连通分量。
https://www.cnblogs.com/stxy-ferryman/p/7779347.html
我觉得他讲得很好。
1 #include <cstdio>
2 #include <cstring>
3 #include <iostream>
4 #include <algorithm>
5 #include <vector>
6 #include <stack>
7 using namespace std;
8 const int MAXN = 1e5 + 20;
9
10 int N, M;
11
12 namespace SCC
13 {
14 vector<int> g[MAXN];
15 stack<int> sta;
16 bool ins[MAXN];
17 int idx[MAXN], dfn[MAXN], low[MAXN];
18 vector<int> scc[MAXN]; int cnt = 0;
19
20 void tarjan(int cur)
21 {
22 static int num = 0;
23 dfn[cur] = low[cur] = ++num;
24 sta.push(cur), ins[cur] = true;
25 for(int i = 0; i < (int) g[cur].size(); i++){
26 int v = g[cur][i];
27 if(!dfn[v]) {
28 tarjan(v);
29 low[cur] = min(low[cur], low[v]);
30 }
31 else if(ins[v]) low[cur] = min(low[cur], dfn[v]);
32 }
33 if(dfn[cur] == low[cur]){
34 ++cnt; int tmp;
35 do{
36 tmp = sta.top(); sta.pop(); ins[tmp] = false;
37 idx[tmp] = cnt, scc[cnt].push_back(tmp);
38 }while(tmp != cur);
39 }
40 }
41 }
42
43 int main()
44 {
45 cin>>N>>M;
46 for(int i = 1, u, v; i <= M; i++){
47 scanf("%d%d", &u, &v);
48 SCC::g[u].push_back(v);
49 }
50
51 for(int i = 1; i <= N; i++)
52 if(!SCC::dfn[i]) SCC::tarjan(i);
53 int ans = 0;
54 for(int i = 1; i <= SCC::cnt; i++)
55 if(SCC::scc[i].size() > 1) ++ans;
56 cout<<ans<<endl;
57 return 0;
58 }