天天看点

二叉苹果树(树型DP+背包)

 二叉苹果树

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)。这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树:

                                            2   5

                                             \  /

                                             3  4

                                              \  /

                                               1

现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

给定需要保留的树枝数量,求出最多能留住多少苹果。

程序名:apple

输入格式:

         第1行2个数,N和Q(1<=Q<= N,1<N<=100)。

         N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。

         每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

         每根树枝上的苹果不超过30000个。

 输出格式:

         一个数,最多能留住的苹果的数量。

 输入样例:

         5 2

         1 3 1

         1 4 10

         2 3 20

         3 5 20

          21

  解题思路:树型DP+背包求解。

                      f(i, j) 表示子树i,保留j个节点(注意是节点)的最大权值。每条边的权值,把它看作是连接的两个节点中的儿子节点的权值。

                      那么,就可以对所有i的子树做分组背包,即每个子树可以选择1,2,...j-1条边分配给它。

                      状态转移为:

                       f(i, j) = max{ max{f(i, j-k) + f(v, k) | 1<=k<j} | v是i的儿子} 

                       ans = f(1, q+1)

  代码如下: