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 } 

 

你可能感兴趣的:(dp)