割点和割边

zhong114514 / 2023-08-16 / 原文

\(x's \text{ } son \in T(x)\)

\(Isn't \text{ }x's \text{ }son \in T'(x)\)

\(x \in Cutpoint,y\in T(x) ,y\notin T'(x)\)

\(i's\text{ dfs order} \to dfn_i\)

$\min(dfn_{f_y,y\in T(x)}) \to low_x $

\(low_{y,y\in T(x)} \ge dfn_x \to CutPoint\)

\(low_{y,y\in T(x)} \gt dfn_x \to CutEdge\)

\(X=Root ,only \text{ } has \text{ } two \text{ } son\)

#include<bits/stdc++.h>

using namespace std;

#define int long long 
#define F(i,a,b) for(int i=a;i<=b;i++)

const int Maxn=2e5+5;

int R,Num_CutPoint,dfn[Maxn],cnt,low[Maxn],n,m;

bool CutPoint[Maxn];

vector<int> to[Maxn];

void dfs(int u){
	low[u]=dfn[u]=++cnt;
	int Son=0;
	for(auto &i:to[u]){
		if(!dfn[i]){
			Son++;dfs(i);low[u]=min(low[u],low[i]);
			if(low[i]>=dfn[u]&&u!=R) Num_CutPoint+=(!CutPoint[u]),CutPoint[u]=1; 
		}else low[u]=min(low[u],dfn[i]);
	}
	if(u==R&&Son>=2) Num_CutPoint+=(!CutPoint[u]),CutPoint[u]=1;
}

signed main(){
	cin>>n>>m;
	for(int i=1,u,v;i<=m;i++){
		cin>>u>>v;
		to[u].push_back(v);
		to[v].push_back(u);
	}
	F(i,1,n) if(!dfn[i]) R=i,dfs(i);
	cout<<Num_CutPoint<<endl;
	F(i,1,n) if(CutPoint[i]) cout<<i<<" " ;
 	return 0;
}