链接:http://poj.org/problem?id=1655
题意: 求树的重心;
树的重心为去掉该节点使其形成的森林中的树的最大的节点数最小;
思路:对于一棵树的任意一个节点做一次DFS就能遍历整棵树, 去掉某节点时, 遍历其子树的节点个数,和为sum那么另一个子树的节点为N-sum-1;
View Code
1 #include <cstdio> 2 #include <cstring> 3 const int M=20005; 4 int T, N, t, ans, r, x, y; 5 int h[M*2], sum[M*2];// re[M*2]; 6 struct Edge 7 { 8 int v, next; 9 }e[M*2]; 10 void AE( int x, int y )// 建边 11 { 12 e[t].v=x, e[t].next=h[y], h[y]=t++; 13 } 14 int Max( int a, int b ) 15 { 16 return a>b?a:b; 17 } 18 void DFS( int s, int f ) 19 { 20 int temp=0; 21 sum[s]=0; 22 re[s]=1; 23 for( int i=h[s]; i!=-1 ; i=e[i].next ){ // 遍历每一个节点 24 int v=e[i].v; 25 if( v==f ) continue; 26 // if( re[v] )continue; 27 DFS( v, s ); 28 temp=Max( temp, sum[v]+1 ); 29 sum[s]+=(sum[v]+1); 30 } 31 temp=Max( temp, N-sum[s]-1 );// 与剩下的一边比较 32 if( ans>temp ){ 33 ans=temp; 34 r=s; 35 } 36 37 38 } 39 int main( ) 40 { 41 scanf( "%d", &T ); 42 while( T -- ){ 43 scanf( "%d", &N ); 44 memset( h, -1, sizeof h ); 45 memset( re, 0, sizeof re ); 46 t=0; 47 for( int i=1; i<N; ++ i ){ 48 scanf( "%d%d", &x, &y ); 49 AE( x, y ); 50 AE( y, x ); 51 } 52 ans=1<<30; 53 DFS( 1, -1 ); 54 printf( "%d %d\n", r, ans ); 55 } 56 return 0; 57 }