思路:求强连通分量的模版题, 答案就是结点个数大于1的强连通分量的个数
#include <iostream>
#include <vector>
#include <cstdio>
#include <stack>
#define sz size()
#define Min(a,b) a<b?a:b
using namespace std;
const int maxn = 10000+10;
//tarjan中需要使用的变量
//------------------------
stack<int> Stack;
int Deep, Sum; //Deep记录搜索了几个点, Sum记录有几个强连通分量
int Dfn[maxn], Low[maxn], Cnt[maxn], Id[maxn]; //Cnt[i]代表第i个强连通分量有几个结点, Id[i]代表结点i属于哪一个强连通分量
bool InStack[maxn];
//------------------------
vector<int> G[maxn];
int n, m, ans;
void tarjan(int cur) {
Dfn[cur] = Low[cur] = ++Deep; //Step1
Stack.push(cur); InStack[cur] = 1; //Step2
for(int i = 0; i < G[cur].sz; i++) { //Step3
int v = G[cur][i];
if(!Dfn[v]) {
tarjan(v);
Low[cur] = Min(Low[cur], Low[v]);
}
else if(InStack[v]) {
Low[cur] = Min(Low[cur], Low[v]);
}
}
if(Dfn[cur] == Low[cur]) { //Step4
int v;
Id[cur] = ++Sum;
Cnt[Sum]++;
while((v = Stack.top()) != cur) {
Stack.pop(); InStack[v] = 0;
Id[v] = Sum;
Cnt[Sum]++;
}
Stack.pop();
}
}
int main() {
int t1, t2;
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d %d", &t1, &t2);
G[t1].push_back(t2);
}
for(int i = 1; i <= n; i++) {
if(!Dfn[i]) {
tarjan(i);
}
}
for(int i = 1; i <= Sum; i++) {
if(Cnt[i] > 1) {
ans++;
}
}
printf("%d\n", ans);
return 0;
}