这道题基于Tarjan的求强连通分量,然后缩点
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
struct EDGE{
int v;
int next;
}edge[55555];
int head[11111],low[11111],dfn[11111],id[11111],out[11111],ans[11111];
int e,depth,cnt,n,m;
stack <int> q;
void addedge(int u,int v){
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}
void dfs(int x){
low[x] = dfn[x] = ++depth;
q.push(x);
for(int i = head[x] ; i != -1 ; i = edge[i].next){
int v = edge[i].v;
if(!dfn[v]){
dfs(v);
low[x] = min(low[v],low[x]);
}
else if(!id[v]){
low[x] = min(dfn[v],low[x]);
}
}
if(low[x] == dfn[x]){
cnt++;
int temp = 0;
int v;
do{
temp++;
v = q.top();
q.pop();
id[v] = cnt;
}while(v != x);
ans[cnt] = temp;
}
return ;
}
void Tarjan(){
cnt = depth = 0;
while(!q.empty()){
q.pop();
}
memset(dfn,0,sizeof(dfn));
for(int i = 1 ; i <= n ; i ++){
if(!dfn[i])
dfs(i);
}
return ;
}
void init(){
e = 0;
memset(id,0,sizeof(id));
memset(head,-1,sizeof(head));
memset(out,0,sizeof(out));
}
int main()
{
while(scanf("%d%d",&n,&m) != EOF){
init();
for(int i = 0 ; i < m ; i ++){
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b);
}
Tarjan();
if(cnt == 1){
printf("%d\n",n);
continue;
}
for(int i = 1 ; i <= n ; i ++){
for(int j = head[i] ; j != -1 ; j = edge[j].next){
int v = edge[j].v;
if(id[i] != id[v]){
out[id[i]]++;
}
}
}
int res = 0;
for(int i = 1 ; i <= cnt ; i ++){
if(!out[i]){
if(!res){
res = ans[i];
}
else
{
res = 0;
break;
}
}
}
printf("%d\n",res);
}
return 0;
}