無向圖的割點板子
阿新 • • 發佈:2018-11-07
/* 基於Tarjan,去掉Tarjan所有有關於棧的操作 判斷一個點u(令其兒子為v)是否為割點: 1. u==root:他的子節點數cnt>1 2. u!=root:low[u]>=dfn[v] //因為如果low[u]<dfn[v] 則說明u點一定有邊可以回溯到v前面形成一個環。 */ #include <cstdio> #include <iostream> #include <algorithm> #include <vector> using namespace std; const int maxn=200005; const int root=1; int n,m; vector<int> g[maxn]; int dfn[maxn],low[maxn],t=0; bool cutpoint[maxn]; int ans[maxn],newp=0; void init(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } } void Tarjan(int u){ dfn[u]=low[u]=++t; int cnt=0; for(int i=0;i<g[u].size();i++){ int v=g[u][i]; if(!dfn[v]){ cnt++; Tarjan(v); if(u!=root&&low[v]>=dfn[u] || u==root&&cnt>1) cutpoint[u]=1; low[u]=min(low[u],low[v]); } else low[u]=min(low[u],dfn[v]); } } void out(){ for(int i=1;i<=n;i++) if(cutpoint[i]) ans[++newp]=i; printf("%d\n",newp); for(int i=1;i<=newp;i++) printf("%d ",ans[i]); } int main(){ init(); for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i); out(); return 0; }