讲解请移步大犇冷老师的讲解
b站讲解视频
代码如下,有空再讲,没有空就算了
#include<bits/stdc++.h>
#include<stack>
#define N 10000000
using namespace std;
int cnt,sum,tot,ans;
int head[N],dfn[N],low[N],vis[N],see[N];
int judge[N];//判断是否联通
stack<int>k;
struct edge{//边集
// int w;
int to;
int from;
}p[N];
void add(int x,int y){//链式前向星存图
cnt++;
// p[cnt].w=z;
p[cnt].to=y;
p[cnt].from=head[x];
head[x]=cnt;
}
void tarjan(int x){
sum++;
dfn[x]=low[x]=sum;
k.push(x);
vis[x]=1;
for(int i=head[x];i;i=p[i].from)
{
int y=p[i].to;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);//情况一
}
else if(vis[y]){
low[x]=min(low[x],dfn[y]);//情况二
}
}
if(low[x]==dfn[x]){
int z;
tot++;//连通编号
while(k.top()!=x){//出栈并标记走过
vis[k.top()]=0;
see[k.top()]=tot;
k.pop();
}
vis[k.top()]=0;
see[k.top()]=tot;
k.pop();
}
return ;
}
int main(){
int n,m;
cin>>n>>m;
int u,v;
for(int i=0;i<m;i++){
cin>>u>>v;
add(u,v);
}
for(register int i=1;i<=n;i++){
if(!dfn[i])
tarjan(i);
}
for(int i=1;i<=n;i++)
for(int j=head[i];j;j=p[j].from)
{
int y=p[j].to;
if(see[i]!=see[y]) judge[see[y]]=1;//边左右节点的编号不同,做标记
}
for(int i=1;i<=tot;i++)
{
if(!judge[i]) ans++;
}
cout<<ans<<endl;
}