正题
其实这道题就是求缩点之后,入度为0的环的大小。
我们跑一便Tarjan缩点之后,记录每个点所在环的编号和大小即可。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stack>
#include<vector>
using namespace std;
int n,m;
int first[10010];
struct edge{
int x,y,next;
}s[100010];
struct node{
int dfn,low;
}op[10010];
int len=0;
bool we[10010];
bool tf[10010];
int where[10010];
int diss[10010];
int node=0;
int tot=0,now=0;
vector<int> T[10010];
stack<int> f;
void ins(int x,int y){
len++;
s[len].x=x;s[len].y=y;s[len].next=first[x];first[x]=len;
}
void Tarjan(int x){
tf[x]=true;f.push(x);
op[x].dfn=op[x].low=++now;
for(int i=first[x];i!=0;i=s[i].next){
int y=s[i].y;
if(op[y].dfn==0){
Tarjan(y);
if(op[y].low<op[x].low) op[x].low=op[y].low;
}
else if(tf[y])
if(op[y].dfn<op[x].low) op[x].low=op[y].dfn;
}
if(op[x].dfn==op[x].low){
tot++;
while(1){
int k=f.top();
f.pop();
T[tot].push_back(k);
where[k]=tot;
tf[k]=false;
if(k==x) break;
}
}
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d %d",&x,&y);
ins(x,y);
}
for(int i=1;i<=n;i++)
if(op[i].dfn==0) Tarjan(i);
for(int i=1;i<=m;i++){
int x=s[i].x,y=s[i].y;
if(where[x]!=where[y])
diss[where[x]]++;
}
int ans=0;
for(int i=1;i<=tot;i++){
if(diss[i]==0){
if(ans==0) ans=T[i].size();
else {
printf("0");
return 0;
}
}
}
printf("%d\n",ans);
}