算法:ural 1018 Binary Apple Tree(树形dp | 经典)

题意

给一棵边有权值的二叉树,节点编号为1~n,1是根节点。求砍掉一些边,只保留q条边,这q条边 构成的子树

的根节点要求是1,问这颗子树的最大权值是多少?

思路

非常经典的一道树形dp题 ,根据我目前做过的题来看,有多道都是由这题衍生出来的。

f(i, j) 表示子树i,保留j个节点(注意是 节点)的最大权值。每条边的权值,把它看作是连接的两个节点中的儿子节点的权值。

那么,就可以对所 有i的子树做分组背包,即每个子树可以选择1,2,...j-1条边分配给它。

状态转移为:

f(i, j) = max{ max{f(i, j-k) + f(v, k) | 1<=k<j} | v是i的儿子}

ans = f(1, q+1)

代码

/**=====================================================
* This is a solution for ACM/ICPC problem
*
* @source : ural-1018 Binary Apple Tree
* @description : 树形dp
* @author : shuangde
* @blog : blog.csdn.net/shuangde800
* @email : zengshuangde@gmail.com
* Copyright (C) 2013/09/01 18:43 All rights reserved.
*======================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#define MP make_pair
using namespace std;

typedef pair<int, int>PII;
typedef long long int64;
const int INF = 0x3f3f3f3f;

const int MAXN = 110;
vector<PII>adj[MAXN];
int n, q;
int tot[MAXN];
int f[MAXN][MAXN];
// http://www.bianceng.cn

int dfs(int u, int fa) {
tot[u] = 1;
for (int e = 0; e < adj[u].size(); ++e) {
int v = adj[u][e].first;
if (v == fa) continue;
tot[u] += dfs(v, u);
}

for (int e = 0; e < adj[u].size(); ++e) {
int v = adj[u][e].first;
int w = adj[u][e].second;
if (v == fa) continue;
for (int i = tot[u]; i > 0; --i) {
for (int j = 1; j < i && j <= tot[v]; ++j) {
f[u][i] = max(f[u][i], f[u][i-j] + f[v][j] + w);
}
}
}
return tot[u];
}

int main(){

while (~scanf("%d%d", &n, &q)) {

for (int i = 0; i <= n; ++i)
adj[i].clear();

for (int i = 0; i < n - 1; ++i) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
adj[u].push_back(MP(v, w));
adj[v].push_back(MP(u, w));
}
memset(f, 0, sizeof(f));
dfs(1, -1);
printf("%d\n", f[1][q+1]);
}
return 0;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索节点
, 分组
, 树形
, 求助一道算法题
, 经典
最大
树形dp、树形dp入门、bzoj 树形dp、poj树形dp、树形dp专题,以便于您获取更多的相关知识。

时间: 2024-09-17 04:49:37

算法:ural 1018 Binary Apple Tree(树形dp | 经典)的相关文章

算法:HDU 2196 Computer(树形dp经典)

题意: 给出一棵树,求离每个节点最远的点的距离 思路: 把无根树转化成有根树分析 , 对于上面那棵树,要求距结点 2的最长距离,那么,就需要知道以2为顶点的子树(蓝色圈起的部分,我们叫它Tree(2)),距顶点2的最 远距离L1 还有知道2的父节点1为根节点的树Tree(1)-Tree(2)部分(即红色圈起部分),距离结点1 的最长距离+dist(1,2) = L2,那么最终距离结点2最远的距离就是max{L1,L2} f[i][0],表示顶点为i 的子树的,距顶点i的最长距离 f[i][1],

算法:poj 2486 Apple Tree (树形背包dp)

题意 给一个n个节点的树,节点编号为1~n, 根节点为1, 每个节点有一个权值. 从根节点出发,走 不超过k步,问最多可以获取多少权值? 思路 因为和uva-1407 caves有点相似,所以没想很久就AC 了,但因为初始化问题WA了两次 f(i, j, 0): 表示子树i,走j次,最终不用回到i点获取的最大总权值 f(i, j, 1): 表示子树i,走j次,最终一定要回到i点获取的最大总权值 f(i, j, 1) = min{ min{ f(i, j-k, 1) + f(v, k-2, 1)

算法:uva 10859 Placing Lampposts (树形dp)

题目大意 给你一个n个点m条边的无向无环图,在尽量少的节点上放灯,使得所有边都被照亮. 每盏灯将照亮以它为一个端点的所有边. 在灯的总数最小的前提下,被两盏灯同时被照亮的边数应该 尽量大. 思路 这是LRJ<训练指南>上的例题. 这题教会了我一个很有用的技巧:有 两个所求的值要优化,比如让a尽量小,b也尽量小 那么可以转化为让 M*a+b尽量小,其中M应该是 一个比"a的最大值和b的最小值之差"还要大的数 最终的答案为ans/M, ans%M 回到这题,要 求放的灯总数最小

算法:poj 3107 Godfather(树形dp)

题意 给一颗n个结点的树,节点编号为1~n,问删除一个节点之后,让剩下的分支中节点数量最多的尽 量少. 可能有多种方案,按编号顺序输出. 思路 简单的树形dp. 其实连dp都不能算吧...就是直接 计数统计 先dfs计算每个节点子树的节点个数tot[i]. 再次dfs更新答案: f[i] = max( n-tot[i], max{tot[v] | v是i的儿子} ); 两个dfs可以合并在一个dfs里完成, 复杂度O(n) 代码 /**==============================

算法:hdu 4044 GeoDefense (树形dp | 多叉树转二叉树)

题意 这是一个塔防游戏,地图是一个n个编号为1-n的节点的树, 节点1是敌人的基地,其他叶子 节点都是你的基地. 敌人的基地会源源不断地出来怪兽,为了防止敌人攻进你的基地,你可以选择造塔. 每个节点最多只能造一个塔,且节点i可以有ki种塔供你选择,价钱和攻击力分别为price_i, power_i 攻击力power_i,效果是让敌人经过这个节点时让敌人的血减少power_i点.   那么从敌人的基地到你 的任意一个基地的路径,这条路径上的所有塔的攻击力之和,就是这个基地的抵抗力. 敌人的攻击路径

算法:uva-10304 Optimal Binary Search Tree(区间dp)

题意 给一个序列即可 S = (e1,e2,...,en),且e1<e2<..<en.要把这些序列构成一个二叉搜索 树. 二叉搜索树是具有递归性质的,且若它的左子树不空,则左子树上所有结点的值均小于它的根结点的 值: 若它 的右子树不空,则右子树上所有结点的值均大于它的根结点的值. 因为在实际应用中,被访 问频率越高的元素,就应该越接近根节点,这样才能更加节省查找时间. 每个元素有一个访问频率f(ei) ,当元素位于深度为k的地方,那么花费cost(ei) = k. 所有节点的花费和访问

算法:poj 2378 Tree Cutting(树形dp)

题意 给一颗n个结点的树,节点编号为1~n,把删除一个节点之后, 剩下的分支中节点数量最多的数 量不大于总数量一半的编号全部按顺序输出 思路 和poj-3107 GodFather完全一样,只是输出不一样. 改为<=n/2的就输出即可. 代码 /**===================================================== * This is a solution for ACM/ICPC problem * * @source : poj-2378 Tree C

算法:poj 1155 TELE (树形背包dp)

题意 某收费有线电视网计划转播一场重要的足球比赛.他们的转播网和用户终端构成一棵树状结 构,这棵树的根结点位于足球比赛的现场,树叶为各个用户终端,其他中转站为该树的内部节点. 从 转播站到转播站以及从转播站到所有用户终端的信号传输费用都是已知的,一场转播的总费用等于传输信号 的费用总和. 现在每个用户都准备了一笔费用想观看这场精彩的足球比赛,有线电视网有权决定给哪 些用户提供信号而不给哪些用户提供信号. 写一个程序找出一个方案使得有线电视网在不亏本的情况 下使观看转播的用户尽可能多. 思路 树形

算法:zoj-3626 Treasure Hunt I (树形dp)

题意 给一棵n个节点的树, 节点编号1~n, 每个节点有权值val[i],经过这个节点就可以获取这个价值( 不能重复获得) 每一条边有一个花费值w(i,j), 表示走完i和j点的边要花费w(i,j) 现在要从k点出发, 总花费值为m,问总花费不超过m的情况下并且最终要回到出发点,最多可以获取多少价值? 思路 简单树形dp. f(i,j)表示子树i, 用花费j最多可以获得的价值 对与i的每个儿子,可以选择分配花费 2*w, 2*w+1, 2*w+2,...j给它,可以看作是一组物品 对所有儿子做分