求割点

版权声明:转载记得声明噢! 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

猜你喜欢

转载自blog.csdn.net/Richard__Luan/article/details/81290481