洛谷 P3388 【模板】割點(割頂)

Love_xyh發表於2020-10-09
這裡求的割點的意義僅僅指的是:去掉這個點後,不能使得原圖聯通的點。
當然可能還會有別的各種各樣的奇怪樹,圖中的不同含義的“割點”。
#include <bits/stdc++.h>
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;
}

相關文章