二叉苹果树——树形Dp(由根到左右子树的转移)
题意:给出一个二叉树,每条边上有一定的边权,并且剪掉一些树枝,求留下 Q 条树枝的最大边权和。 ( 节点数 n ≤100,留下的枝条树 Q ≤ n ,所有边权和 ∑w[i] ≤30000 )
细节:对于一棵子树 u 来说如果剪掉 u 节点上方的树枝,则该子树内的所有树枝都相当于被剪去。
分析:由于是二叉树,所以转移就与左右子树有关,其次我们需要求出最大的边权和,而且需要记录当前子树保留了多少枝条。
所以 Dp 的状态:dp[u][j] 表示以 u 为根保留了 j 条树枝(包括 u 的前一条树枝)
转移: dp[u][j] = max( dp[lx[u]][k] + dp[ly[u]][j-k-1] + Pre[u], dp[u][j] ) lx[u]表示 u 的左子树,ly[u]表示 u 的右子树,Pre[u]表示 u 的前一条边
( j≤size[u],k≤min( size[lx[u]] , j-1) )size[u]表示以 u 为子树的节点个数
代码如下:
#include <bits/stdc++.h>
#define MAXN 105
using namespace std; struct edge{
int to, Next, val;
}Right[MAXN<<];
int Begin[MAXN], f[MAXN][MAXN], Pre[MAXN], size[MAXN], n, q, cnt, lx[MAXN], ly[MAXN]; inline void add_edge(int x, int y, int z){
Right[++cnt].to=y;
Right[cnt].Next=Begin[x];
Begin[x]=cnt;
Right[cnt].val=z;
} void build(int u, int fa){
size[u]=;
for (int i=Begin[u]; i; i=Right[i].Next){
int v=Right[i].to;
if (v==fa) continue;
Pre[v]=Right[i].val;
if (!lx[u]) lx[u]=v;
else ly[u]=v;
build(v, u);
size[u]+=size[v];
}
} void solve(int u, int fa){
for (int i=Begin[u]; i; i=Right[i].Next){
int v=Right[i].to;
if (v==fa) continue;
solve(v, u);
for (int j=; j<=size[u]; j++)
for (int k=; k<=min(size[lx[u]], j-); k++)
f[u][j]=max(f[u][j], f[lx[u]][k]+f[ly[u]][j-k-]+Pre[u]);
}
} int main(){
scanf("%d%d", &n, &q);
for (int i=; i<n; i++){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
add_edge(x, y, z);
add_edge(y, x, z);
}
build(, );
for (int i=; i<=n; i++) f[i][]=Pre[i];
solve(, );
printf("%d\n", f[][q+]);
return ;
}
二叉苹果树——树形Dp(由根到左右子树的转移)的更多相关文章
- 【P2015】二叉苹果树 (树形DP分组背包)
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 现在这颗树枝条太多了,需要剪枝.但是 ...
- P2015 二叉苹果树[树形dp+背包]
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...
- P2015 二叉苹果树 (树形动规)
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来 ...
- Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]
题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修 ...
- 【Luogu】P2015二叉苹果树(DP,DFS)
题目链接 设f[i][j][k]表示给以i为根节点的子树分配j条可保留的树枝名额的时候,状态为k时能保留的最多苹果. k有三种情况. k=1:我只考虑子树的左叉,不考虑子树的右叉,此时子树能保留的最多 ...
- [luoguP2015] 二叉苹果树(DP)
传送门 貌似是个树形背包... 好像吧.. f[i][j]表示节点i选条边的最优解 #include <cstdio> #include <cstring> #include ...
- 二叉苹果树|codevs5565|luoguP2015|树形DP|Elena
二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的 ...
- P2015 二叉苹果树,树形dp
P2015 二叉苹果树 题目大意:有一棵二叉树性质的苹果树,每一根树枝上都有着一些苹果,现在要去掉一些树枝,只留下q根树枝,要求保留最多的苹果数(去掉树枝后不一定是二叉树) 思路:一开始就很直接的想到 ...
- [Luogu2015]二叉苹果树(树形dp)
[Luogu2015] 二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. ...
随机推荐
- JAVA基础之转换流和缓冲流
个人理解: 在理解的字符流和字节流的区别后.要是想读取指定的编码格式的文件时,特别是不是默认的格式时,就需要转换流了,需要注意的是字符流是需要清除缓冲区的:当需要快速的进行读取时,则需要缓冲流.存在即 ...
- columns分栏与flex弹性盒模型
columns 分栏 值:column-width:设置每列的宽度 column-count:设置列数 例:columns{200px 3} 列数和宽度固定 co ...
- HDU 3530Subsequence(单调队列)
题意 题目链接 给出$n$个数,找出最长的区间,使得区间中最大数$-$最小数 $>= m$ 且$<= k$ Sol 考虑维护两个单调队列. 一个维护$1 - i$的最大值,一个维护$1 - ...
- MyBatis关联查询、多条件查询
MyBatis关联查询.多条件查询 1.一对一查询 任务需求; 根据班级的信息查询出教师的相关信息 1.数据库表的设计 班级表: 教师表: 2.实体类的设计 班级表: public class Cla ...
- Vmware Player 比较
.wiz-todo, .wiz-todo-img {width: 16px; height: 16px; cursor: default; padding: 0 10px 0 2px; vertica ...
- python2含有中文路径报错解决办法[\xe4\xbf\xa1\xe6\x81\xaf]
如图所示 百度的解决办法大多数是针对python3版本的,在脚本开头加# -*- coding:utf-8 -*-,但是python2版本加了编码格式,还是报错,具体解决办法是:path =unico ...
- Python+selenium整合自动发邮件功能
主要实现的目的是:自动将测试报告以邮件的形式通知相关人员 from HTMLTestRunner import HTMLTestRunner import HTMLTestReport from em ...
- OpenLayers 3 的 图层控制控件
openlayers3的control中没有提供默认的图层控制控件. 但是git上已经有造好的轮子,直接拿来用就可以了.地址 https://github.com/walkermatt/ol3-lay ...
- 问题驱动的Git学习
(搬运自我在SegmentFault的博客) 本人是个Git新手,平时用Git最多的就是push,因为别的都不怎么会用.这几天因为在小组中负责代码的整合,顺便将代码提交到Github,接触到了Git更 ...
- CF Gym 100187A Potion of Immortality (思路,最坏情况的最小损失)
根据兔子试药情况可以缩小范围,如果死了,不在试过的药里面,如果活着,在试过的药里. 最糟的情况: 两个原则 1.能确定魔药所在的范围的尽量大,2.死得兔子尽量多. 如果当前不知道情况的药n为k的二倍以 ...