Title Link
https://www.luogu.org/problemnew/show/P3388
Template problem
Solving problems
How to find the cutting point?
- dfn: time stamp, dfs order of a graph
- Tree edge: to the child's edge
- Reverse edge: edge connected to ancestor
- low: the edge with the smallest timestamp that a point can reach (only one reverse edge can pass through)
Obviously, if the low of any of its children is greater than or equal to this point, then this point is the cut point.
AC code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<set> 5 #include<stack> 6 using namespace std; 7 const int maxn=20005; 8 const int maxm=200005; 9 int n,m,cnt,dfn[maxn],low[maxn],times,p[maxn]; 10 bool iscut[maxn]; 11 struct edge{ 12 int u; 13 int v; 14 int next; 15 }e[maxm]; 16 stack<edge> S; 17 void insert(int u,int v){ 18 ++cnt; 19 e[cnt].u=u; 20 e[cnt].v=v; 21 e[cnt].next=p[u]; 22 p[u]=cnt; 23 } 24 void dfs(int u,int fa){ 25 dfn[u]=low[u]=++times; 26 int child=0; 27 for(int i=p[u];i!=-1;i=e[i].next){ 28 int v=e[i].v; 29 if(dfn[v]==0){ 30 child++; 31 dfs(v,u); 32 low[u]=min(low[u],low[v]); 33 if(low[v]>=dfn[u])iscut[u]=true; 34 } 35 else if(dfn[v]<dfn[u]&&v!=fa){ 36 low[u]=min(low[u],dfn[v]); 37 } 38 } 39 if(fa==-1&&child==1) iscut[u]=false; 40 } 41 int main() 42 { 43 cin>>n>>m; 44 memset(p,-1,sizeof(p)); 45 memset(low,0x3f3f3f,sizeof(low)); 46 for(int i=1;i<=m;i++){ 47 int x,y; 48 scanf("%d%d",&x,&y); 49 insert(x,y); 50 insert(y,x); 51 } 52 for(int i=1;i<=n;i++){ 53 if(!dfn[i]) dfs(i,-1); 54 } 55 int ans=0; 56 for(int i=1;i<=n;i++){ 57 if(iscut[i]) ans++; 58 } 59 cout<<ans<<endl; 60 for(int i=1;i<=n;i++){ 61 if(iscut[i]) cout<<i<<" "; 62 } 63 return 0; 64 }