洛谷 P2015:二叉苹果树 ← 有依赖的背包问题

【题目来源】
https://www.luogu.com.cn/problem/P2015

【题目描述】
有一棵苹果树,如果树枝有分叉,一定是分二叉(就是说没有只有一个儿子的结点)。
这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为 1∼N,树根编号一定是 1。
我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有 4 个树枝的树:

cpp 复制代码
2   5
 \ / 
  3   4
   \ /
    1

现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
给定需要保留的树枝数量,求出最多能留住多少苹果。
留住一个苹果的定义为苹果所在枝条直接与根相连或通过其他枝条间接与根相连。

【输入格式】
第一行 2 个整数 N 和 Q,分别表示表示树的结点数,和要保留的树枝数量。
接下来 N−1 行,每行 3 个整数,描述一根树枝的信息:前 2 个数是它连接的结点的编号,第 3 个数是这根树枝上苹果的数量。

【输出格式】
一个数,最多能留住的苹果的数量。

【输入样例】
5 2
1 3 1
1 4 10
2 3 20
3 5 20

【输出样例】
21

【数据范围】
1⩽Q<N⩽100,每根树枝上的苹果 ⩽3×10^4。

【算法分析】
● 有依赖的背包(树形背包)核心是物品间存在选子必选父的单向依赖关系,依赖结构通常为森林或多叉树,主流解法为树形 DP 结合分组背包自底向上合并;若题目中是双向强依赖、互相绑定的物品组(选其一必全选),则可先用并查集将连通块缩为超级物品,再套用普通 01 背包求解,两种思路对应不同依赖模型,共同构成完整解法体系。

● 有依赖的背包 / 树形背包 = 选儿子必须先选爹 + 把每个子树当成一组物品

● 邻接表:https://blog.csdn.net/hnjzsyjyj/article/details/155789364

● 核心代码解析
(1)f[u][k] 表示在以 u 为根的子树中,保留 k 根树枝能得到的最大苹果数。
(2)f[u][j]=max(f[u][j],f[u][j-i-1]+f[v][i]+w) 中,j-i-1 表示留给自己其他子树的树枝。-1 表示必须保留 u->v 这一条树枝。

【算法代码】

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int N=105;
vector<pair<int,int>> g[N];
int f[N][N];
int n,V;

void dfs(int u,int fa) {
    for(auto t:g[u]) {
        int v=t.first;
        int w=t.second;
        if(v==fa) continue;
        dfs(v,u);
        for(int j=V; j>=1; j--) {
            for(int i=0; i<j; i++) {
                f[u][j]=max(f[u][j],f[u][j-i-1]+f[v][i]+w);
            }
        }
    }
}

int main() {
    memset(f,0,sizeof f);
    cin>>n>>V;
    for(int i=1; i<n; i++) {
        int x,y,cnt;
        cin>>x>>y>>cnt;
        g[x].push_back({y,cnt});
        g[y].push_back({x,cnt});
    }

    dfs(1,-1);
    cout<<f[1][V]<<endl;

    return 0;
}

/*
in:
5 2
1 3 1
1 4 10
2 3 20
3 5 20

out:
21
*/

【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/159791882
https://blog.csdn.net/hnjzsyjyj/article/details/159616887
https://blog.csdn.net/hnjzsyjyj/article/details/159650172

相关推荐
苏宸啊2 小时前
哈希表开放定址法增删改查简单实现
数据结构·c++
玉小格2 小时前
动态内存管理
数据结构
AnalogElectronic3 小时前
考研408计算机学科专业基础综合 数据结构复习
数据结构·考研·链表
Book思议-5 小时前
【数据结构】二叉树非递归前中后序遍历详解
数据结构·二叉树非递归前中后序遍历
计算机安禾5 小时前
【数据结构与算法】第24篇:哈夫曼树与哈夫曼编码
c语言·开发语言·数据结构·c++·算法·visual studio
郝学胜-神的一滴5 小时前
[力扣 20] 栈解千愁:有效括号序列的优雅实现与深度解析
java·数据结构·c++·算法·leetcode·职场和发展
Yzzz-F5 小时前
Problem - 2148F - Codeforces[字符串后缀排序]
数据结构·算法
Kethy__5 小时前
计算机中级-数据库系统工程师-数据结构-树与二叉树(1)
数据结构·算法··数据库系统工程师·计算机中级
深邃-6 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·算法