题目大意:
根据题目的图很好理解意思,就是记录每一个点的balance,例如 i 的balance就是把 i 从这棵树中除去后得到的森林中含有结点数最多
的子树中的节点个数,然后找到所有节点中对应的balance的最小值 , 并输出最小值对应的最小的标号
题目不要看花。。。前一个是找最大,后面找所有最大值中的最小,我就是看错一直wa,后来人家题解刚看完题目意思就反应过来 , 囧死了 - -
昨天貌似做过一道类似的题,任意找一点 , 比如 1 作为根进行dfs,第一次dfs记录所有点对应的子树中含有的节点的总个数
第二次dfs记录down[i] , 也就是i子树中 i 连接的所有子树中含有节点数最多的节点个数
其实down[i]就相当 i 出去后 , i 下方森林可得到的最大balance , 还需要求一个 i 上方的balance , 这个上方的值就是n-sum[i]
两者比较取最大就可以了
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int N = 20005; 6 int first[N] , k , sum[N] , down[N] , rec[N]; 7 8 struct Edge{ 9 int y , next; 10 }e[N<<1]; 11 12 void add_edge(int x , int y) 13 { 14 e[k].y = y , e[k].next = first[x]; 15 first[x] = k++; 16 } 17 18 void dfs1(int u , int fa) 19 { 20 sum[u] = 1; 21 for(int i=first[u] ; i!=-1 ; i=e[i].next) 22 { 23 int v = e[i].y; 24 if(v == fa) continue; 25 dfs1(v , u); 26 sum[u] += sum[v]; 27 } 28 } 29 void dfs2(int u , int fa) 30 { 31 for(int i=first[u] ; i!=-1 ; i=e[i].next) 32 { 33 int v = e[i].y; 34 if(v == fa) continue; 35 down[u] = max(sum[v]+1 , down[u]); 36 dfs2(v , u); 37 } 38 } 39 40 int main() 41 { 42 // freopen("a.in" , "r" , stdin); 43 int T; 44 scanf("%d" , &T); 45 while(T--) 46 { 47 int n , a , b; 48 scanf("%d" , &n); 49 memset(first , -1 , sizeof(first)); 50 k = 0; 51 for(int i=1 ; i<n ; i++){ 52 scanf("%d%d" , &a , &b); 53 add_edge(a , b); 54 add_edge(b , a); 55 } 56 memset(down , 0 , sizeof(down)); 57 dfs1(1 , -1); 58 dfs2(1 , -1); 59 int minn = down[1]-1; 60 rec[1] = down[1]-1; 61 // cout<<"down: 1: "<<down[1]<<" "<<sum[1]<<endl; 62 for(int i=2 ; i<=n ; i++){ 63 // cout<<"down: i: "<<i<<" "<<" "<<down[i]<<" "<<sum[i]<<endl; 64 rec[i] = max(down[i]-1 , n-sum[i]); 65 minn = min(minn , rec[i]); 66 } 67 int i; 68 for(i=1 ; i<=n ; i++){ 69 if(rec[i] == minn) break; 70 } 71 printf("%d %d " , i , minn); 72 } 73 return 0; 74 }
POJ 3107
求解问题的思想是和上面的题目是基本相同的,除了输入输出方式需要改变,然后数组开大点就可以照抄上面代码了
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int N = 50005; 6 int first[N] , k , sum[N] , down[N] , rec[N]; 7 8 struct Edge{ 9 int y , next; 10 }e[N<<1]; 11 12 void add_edge(int x , int y) 13 { 14 e[k].y = y , e[k].next = first[x]; 15 first[x] = k++; 16 } 17 18 void dfs1(int u , int fa) 19 { 20 sum[u] = 1; 21 for(int i=first[u] ; i!=-1 ; i=e[i].next) 22 { 23 int v = e[i].y; 24 if(v == fa) continue; 25 dfs1(v , u); 26 sum[u] += sum[v]; 27 } 28 } 29 void dfs2(int u , int fa) 30 { 31 for(int i=first[u] ; i!=-1 ; i=e[i].next) 32 { 33 int v = e[i].y; 34 if(v == fa) continue; 35 down[u] = max(sum[v]+1 , down[u]); 36 dfs2(v , u); 37 } 38 } 39 40 int main() 41 { 42 // freopen("a.in" , "r" , stdin); 43 int n , a , b; 44 while(scanf("%d" , &n) == 1){ 45 memset(first , -1 , sizeof(first)); 46 k = 0; 47 for(int i=1 ; i<n ; i++){ 48 scanf("%d%d" , &a , &b); 49 add_edge(a , b); 50 add_edge(b , a); 51 } 52 memset(down , 0 , sizeof(down)); 53 dfs1(1 , -1); 54 dfs2(1 , -1); 55 int minn = down[1]-1; 56 rec[1] = down[1]-1; 57 // cout<<"down: 1: "<<down[1]<<" "<<sum[1]<<endl; 58 for(int i=2 ; i<=n ; i++){ 59 // cout<<"down: i: "<<i<<" "<<" "<<down[i]<<" "<<sum[i]<<endl; 60 rec[i] = max(down[i]-1 , n-sum[i]); 61 minn = min(minn , rec[i]); 62 } 63 int num = 0; 64 for(int i=1 ; i<=n ; i++){ 65 if(rec[i] == minn){ 66 if(num == 0) printf("%d" , i); 67 else printf(" %d" , i); 68 num++; 69 } 70 } 71 } 72 return 0; 73 }