点双连通
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 const int N = 1000+10; 6 const int M = N*N; 7 8 struct Edge { 9 int u, v; 10 Edge( int u, int v ):u(u),v(v){} 11 }; 12 13 int n, m; 14 int head[N], dest[M], next[M], etot; 15 int dfn[N], low[N], bccno[N], iscut[N], bcc_cnt, idc; 16 vector<int> bcc[N]; 17 vector<Edge> stk; 18 19 void adde( int u, int v ) { 20 etot++; 21 dest[etot] = v; 22 next[etot] = head[u]; 23 head[u] = etot; 24 } 25 void dfs( int u, int fa ) { 26 dfn[u] = low[u] = ++idc; 27 int child = 0; 28 for( int t=head[u]; t; t=next[t] ) { 29 int v=dest[t]; 30 if( v==fa ) continue; 31 stk.push_back( Edge(u,v) ); 32 if( !dfn[v] ) { 33 dfs(v,u); 34 low[u] = min( low[u], low[v] ); 35 child++; 36 if( low[v]>=dfn[u] ) { 37 iscut[u] = true; 38 bcc_cnt++; 39 while(1) { 40 Edge e=stk.back(); 41 stk.pop_back(); 42 if( !bccno[e.u] ) bccno[e.u]=bcc_cnt,bcc[bcc_cnt].push_back(e.u); 43 if( !bccno[e.v] ) bccno[e.v]=bcc_cnt,bcc[bcc_cnt].push_back(e.v); 44 if( e.u==u && e.v==v ) break; 45 } 46 } 47 } else if( dfn[v]<dfn[u] ) { 48 low[u] = min( low[u], dfn[v] ); 49 } 50 } 51 if( u==fa && child<=1 ) iscut[u]=false; 52 } 53 int main() { 54 scanf( "%d%d", &n, &m ); 55 for( int i=1,u,v; i<=m; i++ ) { 56 scanf( "%d%d", &u, &v ); 57 adde( u, v ); 58 adde( v, u ); 59 } 60 dfs(1,1); 61 for( int u=1; u<=n; u++ ) 62 if( iscut[u] ) printf( "%d ", u ); 63 printf( "\n" ); 64 }