洛谷 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)fuk 表示在以 u 为根的子树中,保留 k 根树枝能得到的最大苹果数。
(2)fuj=max(fuj,fuj-i-1+fvi+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

相关推荐
kiracrimson10 小时前
从缓存的角度看链表与线性表的差异
数据结构·链表·缓存
心抵鹊11 小时前
归并排序之翻转对(hard)
数据结构·算法
白狐_79814 小时前
408 数据结构|红黑树插入:只记两大类
数据结构
Lost of 程序猿19 小时前
.NET 线程安全集合与并发数据结构深度实战:从 lock 到无锁
数据结构·安全·.net
机器学习之心20 小时前
基于BiGRU-Attention的轴承剩余寿命预测(MATLAB实现):从振动信号到RUL曲线的完整闭环
数据结构·算法·matlab·轴承剩余寿命预测·振动信号·bigru-attention
青梅橘子皮20 小时前
优选算法---专题2(滑动窗口)
数据结构·算法
程序猫.20 小时前
双指针问题
java·数据结构·算法
50万马克的面包20 小时前
数据结构:线性表 —— 顺序表与链表完整总结
数据结构·链表
白狐_79821 小时前
408 数据结构|散列表构造题:开放定址法做题套路
数据结构·散列表
runningshark21 小时前
CH-6图论基础-有向树
数据结构