zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    LeetCode 18. 4Sum (四数之和)
    开运算、闭运算、形态学梯度、顶帽、黑帽
    膨胀和腐蚀
    四种滤波方式
    关于平滑处理及图像滤波与滤波器
    27、简述redis的有哪几种持久化策略及比较?
    26、redis中默认有多少个哈希槽?
    25、如何实现redis集群?
    大聊Python----Select解析
    大聊Python----IO口多路复用
  • 原文地址:https://www.cnblogs.com/orangeko/p/13685640.html
Copyright © 2011-2022 走看看