POJ 1655 Balancing Act (树状dp入门)

Description

Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
For example, consider the tree:

Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.

For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.

Input

The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.

Output

For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.

Sample Input

1
7
2 6
1 2
1 4
4 5
3 7
3 1

Sample Output

1 2

就是给你一棵树,让你在树上去掉一个节点,这样就形成了许多子树,设所有子树中点个数最多的那颗子树的点的个数为x,现在让这个x最小,问你应该剪掉哪个节点,x是多少?
根据树形结构的特殊性,从树根走到叶子节点是严格按照层次顺序的。我现在就开始做dp。首先我们先定义一个dp数组。
我们还需要一个num[x]数组,用来表示以x为树根的子树上有多少节点

对于每一个节点,去掉它所得到的x的值是什么呢?1.它所有子节点为根的子树的最大值 2.除了x和它下面所有的子树,剩下全部的节点。这两者比较最大值就可以了。

刚刚看了白书,就是让找树的重心。
代码如下:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 #define M 20020
 7 int n;
 8 struct Node
 9 {
10     int to,pre;
11 }edge[M*2];
12 int head[M],tot,dp[M],num[M];
13 void init ()
14 {
15     memset(head,-1,sizeof head);
16     tot=0;
17 }
18 void addedge (int u,int v)
19 {
20     edge[tot].to=v;
21     edge[tot].pre=head[u];
22     head[u]=tot++;
23 }
24 void dfs (int u,int prenode)
25 {
26     dp[u]=0;
27     num[u]=1;
28     for (int i=head[u];i!=-1;i=edge[i].pre)
29     {
30         int v=edge[i].to;
31         if (v==prenode)
32         continue;
33         dfs(v,u);
34         dp[u]=max(dp[u],num[v]);
35         num[u]+=num[v];
36     }
37     dp[u]=max(dp[u],n-num[u]);
38 }
39 int main()
40 {
41     int t;
42     scanf("%d",&t);
43     while (t--)
44     {
45         scanf("%d",&n);
46         init();
47         for (int i=1;i<n;++i)
48         {
49             int u,v;
50             scanf("%d %d",&u,&v);
51             addedge(u,v);
52             addedge(v,u);
53         }
54         dfs(1,-1);
55         int ans1=1,ans2=dp[1];
56         for (int i=2;i<=n;++i)
57         {
58             if (ans2>dp[i])
59             {
60                 ans1=i;
61                 ans2=dp[i];
62             }
63         }
64         printf("%d %d
",ans1,ans2);
65     }
66     return 0;
67 }
原文地址:https://www.cnblogs.com/agenthtb/p/5948396.html