强连通分量可以看作一组点 这组点中任意两个都是可到达的 然后把这一组点抽象成一个点即可
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 1e5+100;
const int maxm = 500010;
struct Edge{
int to,next;
}edge[maxm];
int head[maxn];
int tot;
int low[maxn],dfn[maxn],stack[maxn],belong[maxn];
//low 第几组强连通分量
//dfn 遍历的顺序
//belong 属于第几组强连通分量
int Index,top;
int scc;
bool instack[maxn];
int num[maxn];//每组强连通分量的节点数量
void addedge(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
void Tarjan(int u){
int v;
low[u] = dfn[u] = ++Index;
stack[top++] = u;
instack[u] = true;
for(int i = head[u];i!=-1;i = edge[i].next){
v = edge[i].to;
if(!dfn[v]){
Tarjan(v);
low[u] = min(low[u],low[v]);
}
else if(instack[v]&&low[u]>dfn[v]){
low[u] = dfn[v];
}
}
if(low[u]==dfn[u]){
scc++;
do{
v = stack[--top];
instack[v] = false;
belong[v] = scc;
num[scc]++;
}
while(v!=u);
}
}
void solve(int N){
memset(dfn,0,sizeof(dfn));
memset(instack,false,sizeof(stack));
memset(num,0,sizeof(num));
Index = scc = top = 0;
for(int i = 1;i<=N;++i){
if(!dfn[i]){
Tarjan(i);
}
}
}
void init(){
tot = 0;
memset(head,-1,sizeof(head));
}
int out[maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
init();
for(int i = 1;i<=m;++i){
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
}
solve(n);
for(int i = 1;i<=n;++i){
for(int j = head[i];j!=-1;j = edge[j].next){
int v = edge[j].to;
if(belong[v]!=belong[i]){
out[belong[i]]++;
}
}
}
int ind = -1;
for(int i = 1;i<=scc;++i){
if(out[i]==0&&ind>0){
printf("0\n");
return 0;
}
if(out[i]==0){
ind = i;
}
}
printf("%d\n",num[ind]);
}