如果有x满足答案,x所在的scc也满足答案
合法scc个数不会超过1,因为这样的话2个scc是传递的,应该可以合并才对
这个板子做法是按照拓扑序排列缩点后的图的,所以可能成为答案的scc一定是最后那个
//#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<stack>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define mem(a) memset(a,0,sizeof a)
#define FOR(a) for(int i=1;i<=a;i++)
const int maxn=1e4+6;
int V;
vector<int>G[maxn];
vector<int>rG[maxn];
vector<int>vs; //后续
bool used[maxn];
int cmp[maxn]; //所属连通分量拓扑序
void addedge(int u,int v){
G[u].pb(v);rG[v].pb(u);
}
void dfs(int u){
used[u]=1;
for(int i=0;i<G[u].size();i++){
if(!used[G[u][i]])dfs(G[u][i]);
}
vs.pb(u);
}
void rdfs(int u,int k){
used[u]=1;
cmp[u]=k;
for(int i=0;i<rG[u].size();i++){
if(!used[rG[u][i]])rdfs(rG[u][i],k);
}
}
int scc(){
memset(used,0,sizeof used);
vs.clear();
for(int i=1;i<=V;i++){
if(!used[i])dfs(i);
}
memset(used,0,sizeof used);
int k=0;
for(int i=vs.size()-1;i>=0;i--){
if(!used[vs[i]])rdfs(vs[i],++k);
}
return k;
}
int n,m;
int main(){
scanf("%d%d",&n,&m);V=n;
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
}
n=scc();
int u=1,num=0;
for(int i=1;i<=V;i++){
if(cmp[i]==n){
u=i;num++;
}
}
memset(used,0,sizeof used);
rdfs(u,0);
for(int i=1;i<=V;i++){
if(!used[i]){
num=0;
break;
}
}
printf("%d\n",num);
}