POJ 2378 Tree Cutting

题目大意

给定一个无向图形成一棵树,截去某个点后,森林中的树要是每棵树中的节点数都不超过原来总结点数的1/2,那么就把这个点输出

否则输出NONE

前面也做了思想一样的题目POJ 1655 Balancing Act && POJ 3107 Godfather

不理解可以看看

 1 /*
 2 sum[i]表示i对应子树中的节点总数
 3 down[i]表示截去i后,i下方子树断开成森林中最大的那棵子树的节点数
 4 i取走后,往上走的子树长度为 n -sum[i]
 5 rec[i] = max(down[i] , n -sum[i]);
 6 */
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <iostream>
10 using namespace std;
11 
12 const int N = 10005;
13 int first[N] , k , down[N] , sum[N] , rec[N];
14 
15 struct Edge{
16     int y , next;
17 }e[N<<1];
18 
19 void add_edge(int x , int y)
20 {
21     e[k].y = y , e[k].next = first[x];
22     first[x] = k++;
23 }
24 
25 void  dfs1(int u , int fa)
26 {
27     sum[u] = 1;
28     for(int i = first[u] ; i!=-1 ; i=e[i].next)
29     {
30         int v = e[i].y;
31         if(v == fa) continue;
32         dfs1(v , u);
33         sum[u] += sum[v];
34     }
35 }
36 
37 void dfs2(int u , int fa)
38 {
39     for(int i = first[u] ; i!=-1 ; i=e[i].next)
40     {
41         int v = e[i].y;
42         if(v == fa) continue;
43         dfs2(v , u);
44         down[u] = max(sum[v] , down[u]);
45     }
46 }
47 
48 int main()
49 {
50    // freopen("a.in" , "r" , stdin);
51     int n , x , y;
52     while(scanf("%d" , &n)==1){
53         memset(first , -1 , sizeof(first));
54         k=0;
55         for(int i=1 ; i<n ; i++){
56             scanf("%d%d" , &x , &y);
57             add_edge(x , y);
58             add_edge(y , x);
59         }
60 
61         memset(down , 0 , sizeof(down));
62         dfs1(1 , -1);
63         dfs2(1 , -1);
64         int num=0;
65         for(int i=1 ; i<=n ; i++){
66             rec[i] = max(down[i] , n-sum[i]);
67             if(rec[i]<=n/2){
68                 printf("%d
" , i);
69                 num++;
70             }
71         }
72         if(num == 0) puts("NONE");
73     }
74     return 0;
75 }
原文地址:https://www.cnblogs.com/CSU3901130321/p/4234026.html