题面:
割点性质:
节点 u 如果是割点,当且仅当存在 u 的一个子树,子树中没有连向 u 的祖先的边(返祖边)。
换句话说,如果对于一个点u,它的子节点是v,如果low[v]>=dfn[u],就代表u的子图中没有返祖边,即该节点u是割点;
#include <bits/stdc++.h> using namespace std; int n,m; struct littlestar{ int to; int nxt; }star[400000]; int head[400000],cnt; void add(int u,int v) { star[++cnt].to=v; star[cnt].nxt=head[u]; head[u]=cnt; } int dfn[20000],low[20000]; int num; int co[20000]; void tarjan(int u,int fa) { dfn[u]=low[u]=++num; for(int i=head[u];i;i=star[i].nxt){ int v=star[i].to; if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); if(fa&&low[v]>=dfn[u]){ co[u]=1; //注意,不可以在这里统计割点次数,因为有的点可能会多次进入该判断语句,比如说菊花图。 } } else if(v!=fa) { low[u]=min(low[u],dfn[v]); } } } int main () { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i,0); } int col=0; for(int i=1;i<=n;i++){ if(co[i]){ ++col; } } cout<<col<<endl; for(int i=1;i<=n;i++){ if(co[i]){ cout<<i<<" "; } } }