qyy想出了某道题怎么做,就是要求一次割点 , 但是 ,qwq ,当时还不会 ,所以就学一学割点的求法,好像大家都是用tarjan搞的,没看到其它做法 。
然后贴一下版
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cstdio> 5 #include <queue> 6 const int inf = 1 << 30 , maxn = 100000 + 11 ; 7 using namespace std ; 8 int n , m , head[maxn] , cnt , dfn[maxn] , low[maxn] , t , root , son , ans[maxn] ; 9 bool lock[maxn] , c[maxn] ; 10 struct id 11 { 12 int nxt , to ; 13 }edge[maxn<<1] ; 14 15 int read( ) 16 { 17 char ch = getchar( ) ; int k = 1 , ret = 0 ; 18 while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar( ) ; } 19 while( ch >= '0' && ch <= '9' ) { ret = ret * 10 + ch - '0' , ch = getchar( ) ; } 20 return ret * k ; 21 } 22 23 24 void add( int u , int v ) 25 { 26 edge[++cnt].to = v , edge[cnt].nxt = head[u] ; 27 head[u] = cnt ; 28 } 29 30 31 void scc( int dep , int u ) 32 { 33 dfn[u] = low[u] = dep ; 34 for( int i = head[u] ; i ; i = edge[i].nxt ) 35 { 36 int v = edge[i].to ; 37 if( !dfn[v] ) 38 { 39 scc( dep + 1 , v ) ; 40 if( u == root ) son ++ ; 41 else 42 { 43 low[u] = min( low[u] , low[v] ) ; 44 if( dfn[u] <= low[v] ) 45 c[u] = true ; 46 } 47 } 48 else low[u] = min( low[u] , dfn[v] ) ; 49 } 50 } 51 52 void sov( ) 53 { 54 n = read( ) , m = read( ) ; 55 int a , b ; 56 for( int x = 1 ; x <= m ; ++x ) 57 { 58 a = read( ) , b = read( ) ; 59 add( a , b ) ; 60 add( b , a ) ; 61 } 62 root = 1 , son = 0 ; 63 memset( lock , false , sizeof(lock) ) ; 64 memset( c , false , sizeof( c ) ) ; 65 scc( 1 , root ) ; 66 if( son > 1 ) c[1] = 1 ; 67 68 } 69 70 void output( ) 71 { 72 int tot = 0 ; 73 for( int x = 1 ; x <= n ; ++x ) 74 if( c[x] ) ans[++tot] = x ; 75 printf( "%d " , tot ) ; 76 for( int x = 1 ; x <= tot ; ++x ) 77 printf( "%d " , ans[x] ) ; 78 printf( " " ) ; 79 } 80 81 82 int main( ) 83 { 84 sov( ) ; 85 output( ) ; 86 return 0 ; 87 }