Given an n-point, M-edge of the graph, to find the cut point.
U is the two conditions of cut vertex:
1. Presence v causes V and all its descendants to have no reverse edge to connect back to u ancestors
2.U is root and has more than two child nodes
DFS again
Low[u] is the earliest ancestor that u and its descendants can connect back to
No dfn[v] on DFS (v), then update low[u with Low[v] (V is the descendant of U)
Otherwise v is not FA just use DFN[V] update low[u] (U can be connected back to V) "cannot use Low[v], because Low[v] contains the descendants of V can be connected back to"
#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespacestd;Const intn=1e5+5, m=1e5+5, inf=1e9+5; inlineintRead () {CharC=getchar ();intx=0, f=1; while(c<'0'|| C>'9'){if(c=='-') f=-1; c=GetChar ();} while(c>='0'&&c<='9') {x=x*Ten+c-'0'; c=GetChar ();} returnx;}intn=0, m,u,v;structedge{intV,ne;} E[m<<1];intH[n],cnt=0; inlinevoidInsintUintv) {CNT++; E[CNT].V=v;e[cnt].ne=h[u];h[u]=CNT; CNT++; E[CNT].V=u;e[cnt].ne=h[v];h[v]=CNT;}intDfn[n],low[n],dfc=0, iscut[n];voidDfsintUintFA) {Dfn[u]=low[u]=++DFC; intChild=0; for(intI=h[u];i;i=e[i].ne) { intv=e[i].v; if(!Dfn[v]) { Child++; DFS (V,U); Low[u]=min (low[u],low[v]); if(Low[v]>=dfn[u]) iscut[u]=1; }Else if(DFN[V]<DFN[U]&&V!=FA) low[u]=min (low[u],dfn[v]); } if(fa==0&&child==1) iscut[u]=0;}intMain () {n=read (); m=read (); for(intI=1; i<=m;i++) {u=read (); v=read (); Ins (u,v);} for(intI=1; i<=n;i++)if(!dfn[i]) DFS (i,0); intans=0; for(intI=1; i<=n;i++)if(Iscut[i]) ans++; printf ("%d\n", ans); for(intI=1; i<=n;i++)if(Iscut[i]) printf ("%d", i);}
Rokua P3388 "template" Cut point