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\n" , i);

69                 num++;

70             }

71         }

72         if(num == 0) puts("NONE");

73     }

74     return 0;

75 }

 

你可能感兴趣的:(tree)