P2015 二叉苹果树【树形背包】

题目描述

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

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

2   5
  / 
  3   4
    /
    1

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

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

输入格式

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

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

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

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

输出格式

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

输入输出样例

输入 #1
5 2
1 3 1
1 4 10
2 3 20
3 5 20
输出 #1
21

题解:
  树形背包模板题,考虑到每次删减最小的边有后效性,无法得出正解可以考虑背包
  f[u][i]表示以u为根节点的拥有i条边的子树拥有的最大苹果数量。
  显然转移方程可以写成:
      f[u][i] = max(f[u][i], f[u][i - j + 1] + f[v][j] + w[i])
  接着直接套树形背包的模板即可。

CODE
 1 #include <bits/stdc++.h>
 2 #define dbug(x) cout << #x << "=" << x << endl
 3 #define eps 1e-8
 4 #define pi acos(-1.0)
 5  
 6 using namespace std;
 7 typedef long long LL;
 8  
 9 const int inf = 0x3f3f3f3f;
10  
11 template<class T>inline void read(T &res)
12 {
13    char c;T flag=1;
14    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
15    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
16 }
17 
18 const int maxn = 2e5 + 7;
19 
20 int n, q;
21 
22 int cnt, w[maxn], head[maxn], nxt[maxn], edge[maxn];
23 int ans = 0;
24 
25 int f[107][107];
26 
27 void BuildGraph(int u, int v, int c) {
28     ++cnt;
29     edge[cnt] = v;
30     nxt[cnt] = head[u];
31     head[u] = cnt;
32     w[cnt] = c;
33 }
34 
35 void dfs(int u, int fa) {
36     for ( int i = head[u]; i; i = nxt[i] ) {
37         int v = edge[i];
38         if(v == fa) {
39             continue;
40         }
41         dfs(v, u);
42         for ( int j = q; j; --j ) {
43             for ( int k =j - 1; k >= 0; --k ) {
44                 f[u][j] = max(f[u][j], f[u][j - k - 1] + f[v][k] + w[i]);
45                 // printf("f[%d][%d]:%d
",u, j, f[u][j]);
46             }
47         }
48     }
49 }
50 
51 int main()
52 {
53     read(n); read(q);
54     for ( int i = 1; i <= n - 1; ++i ) {
55         int u, v, w;
56         read(u); read(v); read(w);
57         BuildGraph(u, v, w);
58         BuildGraph(v, u, w);
59     }
60     dfs(1, 1);
61     for ( int i = 1; i <= n; ++i ) {
62         ans = max(f[i][q], ans);
63     }
64     ans = f[1][q];
65     cout << ans << endl;
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/orangeko/p/13685640.html