二叉苹果树
二叉苹果树
有一棵二叉苹果树,如果树枝有分叉,一定是分两叉,即没有只有一个儿子的节点。
这棵树共 个节点,编号为 至 ,树根编号一定为 。
我们用一根树枝两端连接的节点编号描述一根树枝的位置。
一棵苹果树的树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。
这里的保留是指最终与 号点连通。
输入格式
第一行包含两个整数 和 ,分别表示树的节点数以及要保留的树枝数量。
接下来 行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。
输出格式
输出仅一行,表示最多能留住的苹果的数量。
数据范围
.
,
每根树枝上苹果不超过 个。
输入样例:
5 2 1 3 1 1 4 10 2 3 20 3 5 20
输出样例:
21
解题思路
这是有依赖的背包问题的简化版。因为选择的树枝要和根节点连通,因此可以把每个节点看成是物品,如果要选择这个物品就一定要选择这个物品的根节点,因此就存在一个依赖关系。把每个边的价值转变到节点的价值,然后每个节点的体积都为,就可以转化成有依赖的背包问题。
用来表示在以为根的子树中选择条边的最大价值。把以为节点的树的每一个子节点看成是各组物品,再根据各个物品组选择不同的边数进行状态转移。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 110, M = N * 2; 5 6 int n, m; 7 int head[N], e[M], wts[M], ne[M], idx; 8 int f[N][N]; 9 10 void add(int v, int w, int wt) { 11 e[idx] = w, wts[idx] = wt, ne[idx] = head[v], head[v] = idx++; 12 } 13 14 void dfs(int u, int pre) { 15 for (int i = head[u]; i != -1; i = ne[i]) { 16 if (e[i] != pre) { 17 dfs(e[i], u); 18 for (int j = m; j; j--) { 19 for (int k = 0; k < j; k++) { 20 f[u][j] = max(f[u][j], f[u][j - k - 1] + f[e[i]][k] + wts[i]); 21 } 22 } 23 } 24 } 25 } 26 27 int main() { 28 scanf("%d %d", &n, &m); 29 30 memset(head, -1, sizeof(head)); 31 for (int i = 0; i < n - 1; i++) { 32 int v, w, wt; 33 scanf("%d %d %d", &v, &w, &wt); 34 add(v, w, wt), add(w, v, wt); 35 } 36 37 dfs(1, -1); 38 printf("%d", f[1][m]); 39 40 return 0; 41 }
参考资料
AcWing 1074. 二叉苹果树(算法提高课):https://www.acwing.com/video/416/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16552605.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效