POJ 1655 Balancing Act && POJ 3107 Godfather

题目大意:

根据题目的图很好理解意思,就是记录每一个点的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\n" , 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 }

 

你可能感兴趣的:(poj)