HDOJ树形DP专题之Balancing Act

题目链接

题目大意:给定一棵树,树的每个结点有一个权值,每个结点的权值=去掉该结点后剩余的分支中结点最多的那个分支的结点数。求树中权值最小的结点。

这题CE了两次,第一次因为使用了memset没包含头文件,第二次是因为GNU C++没有头文件<memory.h>,使用<string.h>就AC了。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #define N 20000
 5 #define MAX(a,b) ((a)>(b)?(a):(b))
 6 using namespace std;
 7 vector<int> g[N];
 8 int n,p[N],d[N],sum[N],w[N],dmax;
 9 void dfs(int u,int fa)
10 {
11   int i,v;
12   d[u]=(fa==-1?0:d[fa]+1);
13   dmax=MAX(dmax,d[u]);
14   for(i=0;i<g[u].size();i++)
15   {
16     v=g[u][i];
17     if(v!=fa) dfs(v,p[v]=u);
18   }
19 }
20 void dp()
21 {
22   int i,j;
23   memset(w,0,sizeof(w));
24   for(i=0;i<n;i++)  sum[i]=1;
25   for(i=dmax;i>=0;i--)
26   {
27     for(j=0;j<n;j++)
28     {
29       if(d[j]!=i) continue;
30       w[j]=MAX(w[j],n-sum[j]);
31       if(i>0) w[p[j]]=MAX(w[p[j]],sum[j]),sum[p[j]]+=sum[j];
32     }
33   }
34 }
35 int main()
36 {
37   int i,t,u,v,min;
38   scanf("%d",&t);
39   while(t--)
40   {
41     scanf("%d",&n);
42     for(i=0;i<n;i++)  g[i].clear();
43     for(i=0;i<n-1;i++)
44     {
45       scanf("%d%d",&u,&v);
46       u--,v--;
47       g[u].push_back(v);
48       g[v].push_back(u);
49     }
50     dmax=0;
51     dfs(0,-1);
52     dp();
53     min=0x7fffffff;
54     for(i=0;i<n;i++)  if(w[i]<min)  min=w[u=i];
55     printf("%d %d\n",u+1,min);
56   }
57   return 0;
58 } 

 

posted @ 2012-04-27 15:08  BeatLJ  阅读(286)  评论(0编辑  收藏  举报