洛谷 P3388 【模板】割点(割顶)

这里求的割点的意义仅仅指的是:去掉这个点后,不能使得原图联通的点。
当然可能还会有别的各种各样的奇怪树,图中的不同含义的“割点”。
#include 
using namespace std;
const int N=1e5+5;
int n,m,u,v,now,cnt,ans;
int head[N],dfn[N],low[N];
bool cut[N];
struct edge{
     int next,to;}e[2*N];

inline void add(int u,int v)
{
     
	cnt++;	
	e[cnt].next=head[u];
	e[cnt].to=v;
	head[u]=cnt;
}

void tarjan(int u,int fa)
{
     
	int son=0;
	dfn[u]=low[u]=++now;
	for (register int i=head[u]; i; i=e[i].next)
	{
     
		if (!dfn[e[i].to])
		{
     
			tarjan(e[i].to,fa);
			low[u]=min(low[u],low[e[i].to]);
			if (u!=fa && low[e[i].to]>=dfn[u]) cut[u]=true;
			if (u==fa) son++;
		}
		else low[u]=min(low[u],dfn[e[i].to]);
		//强连通分量里是low[u]=min(low[u],low[e[i].to])
		//割点是low[u]=min(low[u],dfn[e[i].to]) 
	}
	if (son>=2 && u==fa) cut[u]=true;
}

int main(){
     
	scanf("%d%d",&n,&m);
	for (register int i=1; i<=m; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
	for (register int i=1; i<=n; ++i) if (!dfn[i]) tarjan(i,i);
	for (register int i=1; i<=n; ++i) if (cut[i]) ans++;
	printf("%d\n",ans);
	for (register int i=1; i<=n; ++i) if (cut[i]) printf("%d ",i);
return 0;
}

你可能感兴趣的:(割点)