版权声明:转载记得声明噢! https://blog.csdn.net/Richard__Luan/article/details/81290481
模板
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#define MAXN 100005
#define MAXM 2000005
using namespace std;
int n,m;
int dfn[MAXN],low[MAXN],st[MAXN],top,scc;
bool cut[MAXN];
int fst[MAXN],nxt[MAXM],vv[MAXM];
vector<int> v[MAXN];
int cnt;
long long ans,fun;
int root;
int edge;
void dfs(int x,int pre)
{
dfn[x]=low[x]=++cnt;//时间戳
st[++top]=x;//栈
int num=0;
for(int i=fst[x];i;i=nxt[i])
{
if(vv[i]==pre)continue;
if(!dfn[vv[i]])
{
num++;
dfs(vv[i],x);
low[x]=min(low[x],low[vv[i]]);
if(low[vv[i]]>=dfn[x])
{
v[++scc].clear();
if(x==root)//根需要特判
{
if(num>1)cut[x]=1;
}
else cut[x]=1;
while(st[top]!=x)v[scc].push_back(st[top--]);//弹栈 在同一个点双联通分量
v[scc].push_back(x);//割点在多个点双内
}
}
else low[x]=min(low[x],dfn[vv[i]]);
}
}
void add(int x,int y)
{
edge++;
nxt[edge]=fst[x];
fst[x]=edge;
vv[edge]=y;
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
int maxx=-1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
root=i,dfs(i,-1);
}
for(int i=1;i<=n;i++)
ans+=cut[i];
printf("%lld",ans);
return 0;
}
odk