标签:
Description
Input
Output
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\n",ans1,ans2); 65 } 66 return 0; 67 }
POJ 1655 Balancing Act (树状dp入门)
标签:
原文地址:http://www.cnblogs.com/agenthtb/p/5948396.html