割点(tarjan)
对于根来说,如果它有超过1棵子树,那么它是一个割点
对于非叶结点来说,如果它的某一个儿子没有回边能到达高于它的点,那么它是一个割点
叶节点不是割点
//洛谷3388 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstdio> #define nn 100011 using namespace std; int tim=0,tail=0,e=0,st; int t[nn],top[nn],fir[nn],q[nn],sta[nn],vis[nn],nxt[nn<<1],to[nn<<1]; int read() { int ans=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();} return ans*f; } void add(int u,int v) { nxt[++e]=fir[u];fir[u]=e;to[e]=v; nxt[++e]=fir[v];fir[v]=e;to[e]=u; } void tarjan(int x,int fa) { int son=0,cut=0; t[x]=top[x]=++tim; for(int i=fir[x];i;i=nxt[i]) if(!t[to[i]]) { tarjan(to[i],x);son++; top[x]=min(top[x],top[to[i]]); if(fa&&top[to[i]]>=t[x]) //不是根节点 cut=1; } else if(to[i]!=fa) top[x]=min(top[x],t[to[i]]); if(!fa&&son>1) cut=1; if(cut) q[++tail]=x; } int main() { int n,m,u,v; n=read();m=read(); for(int i=1;i<=m;i++) { u=read();v=read(); add(u,v); } for(int i=1;i<=n;i++) if(!t[i]) tarjan(i,0); sort(q+1,q+tail+1); printf("%d\n",tail); for(int i=1;i<=tail;i++) printf("%d ",q[i]); return 0; }