苹果树

AcWing 1074 二叉苹果树

一笑奈何 提交于 2020-02-27 06:38:09
题目描述: 有一棵二叉苹果树,如果树枝有分叉,一定是分两叉,即没有只有一个儿子的节点。 这棵树共 N 个节点,编号为 1 至 N,树根编号一定为 1。 我们用一根树枝两端连接的节点编号描述一根树枝的位置。 一棵苹果树的树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。 这里的保留是指最终与1号点连通。 输入格式 第一行包含两个整数 N 和 Q,分别表示树的节点数以及要保留的树枝数量。 接下来 N−1 行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。 输出格式 输出仅一行,表示最多能留住的苹果的数量。 数据范围 1≤Q<N≤100. N≠1, 每根树枝上苹果不超过 30000 个。 输入样例: 5 2 1 3 1 1 4 10 2 3 20 3 5 20 输出样例: 21 分析: 本题与 AcWing 10 有依赖的背包问题 十分相似,不过有依赖的背包问题是选择一个顶点前必须选择它的父节点,而本题是选择某条边前要确保其父节点也被选中了,也就是说一个是点权一个是边权问题。先回顾下分组背包问题的代码: for(int i = 1;i <= n;i++) for(int j = m;j >= 0;j--) for(int k = 1;k <= s[i];k++) if(j >= v[i][k]) f[j] =

AC日记——苹果树 codevs 1228

微笑、不失礼 提交于 2020-01-10 03:10:37
1228 苹果树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在卡卡的房子外面,有一棵苹果树。每年的春天,树上总会结出很多的苹果。卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树。我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起。卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强。 卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果。 于是我们定义两种操作: C x 表示编号为x的分叉点的状态被改变(原来有苹果的话,就被摘掉,原来没有的话,就结出一个苹果) G x 查询编号为x的分叉点所代表的子树中有多少个苹果 我们假定一开始的时候,树上全都是苹果,也包括作为根结点的分叉1。 输入描述 Input Description 第一行一个数N (n<=100000) 接下来n-1行,每行2个数u,v,表示分叉点u和分叉点v是直接相连的。 再接下来一行一个数M,(M<=100000)表示询问数 接下来M行,表示询问,询问的格式如题目所述Q x或者C x 输出描述 Output Description 对于每个Q x的询问,请输出相应的结果

[HAOI2018]苹果树题解

房东的猫 提交于 2019-12-09 09:46:39
题目链接 大意:不解释 思路: 首先方案数共有 n !种,第 1 个点只有 1 种选择,第 2 个点 2 种选择,生成 2 个选择的同时消耗一个,第 3 个点则有 3 种选择,依次类推共有 n! 种方案,由于最后答案 *n !,故输出的实际上是每种方案的总和。 由于枚举方案是不可行的,考虑枚举边,计算每一个点连向父亲的边的贡献,容易知道贡献为 siz*(n-siz) , siz 为子树大小。 所以枚举点与 siz 即可。再考虑组成子树的形态,与子树外的形态。设当前枚举到 i 号点,子树大小为 siz ,则子树内不考虑编号有 siz! 种形态 , 考虑编号则有 C(n-i,siz-1) 种编号组合 , 则子树内共有 siz!*C(n-i,siz-1) 种方案;考虑子树外:由于已有 i 个点,这 i 个点可以有 i !种方案 , 从第 i+siz-1 点开始由于以 i 为根的子树 siz 已确定,故这个点不能插入到以 i 为根的子树内,所以只有 i-1 种选择 , 这一部分贡献为 (i-1)*(i)*(i+1)* …… *(n-siz-1) ,与前面的总和化简得 i*(i-1)*(n-siz-1)! 。则当前枚举的点 i 与 siz 对答案的贡献为 siz*(n-siz)*i*(i-1)*(n-siz-1)!*C(n-i,siz-1)*siz! 。预处理出组合和阶乘枚举点 i 和

luogu P2015 二叉苹果树

懵懂的女人 提交于 2019-12-06 19:20:44
嘟嘟嘟 这应该算一道树形背包吧,虽然我还是分不太清树形背包和树形dp的区别…… 首先dp[i][u][j] 表示在u的前 i 棵子树中,留了 j 条树枝时最大的苹果数量,而且根据题目描述,这些留下的树枝一定都连在u上。 然后我们从1~j 枚举 k,于是   dp[i][u][j] = max(dp[i - 1][u][j], dp[i - 1][u][j - k] + dp[i - 1][v][k - 1] + cost[u->v]) 思路就是我们让v所在的子树和u相连取更新答案。 j 的范围是枚举到当前的v时,u的子树中树枝的数量。 然后我们可以把第一维优化掉。 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x,

P2015 二叉苹果树(树形DP)

*爱你&永不变心* 提交于 2019-12-06 19:19:30
P2015 二叉苹果树 https://www.luogu.org/problemnew/show/P2015 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100)。 N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。 每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过30000个。 输出格式: 一个数,最多能留住的苹果的数量。 输入输出样例 输入样例#1: 5 2 1 3 1 1 4 10 2 3 20 3 5 20 输出样例#1: 21 思路:树形DP好题 1 import java.util.ArrayList; 2 import java.util.Scanner; 3 4 class node{ 5 int v; 6 int w; 7 } 8 public class 树形DP { 9

Luogu P2015 二叉苹果树 (树形DP)

ぃ、小莉子 提交于 2019-12-06 19:18:55
题目 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有1个儿子的结点) 这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为 1-N ,树根编号一定是 1 。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有 4 个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 输入输出格式 输入格式: 第 1 行 2 个数, N 和 Q ( 1<=Q<=N , 1<N<=100 )。 N 表示树的结点数, Q 表示要保留的树枝数量。接下来 N-1 行描述树枝的信息。 每行 3 个整数,前两个是它连接的结点的编号。第 3 个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过 30000 个。 输出格式: 一个数,最多能留住的苹果的数量。 输入输出样例 输入样例: 5 2 1 3 1 1 4 10 2 3 20 3 5 20 输出样例: 21 题解 也是树形DP经典入门题,我这里用了记忆化搜索 dp[i][j] 表示 i 结点下剩余 j 条边留下的苹果最大值 代码 #include <bits/stdc++.h> using namespace std; struct node { int value, left, right, father; }

Luogu P2015 二叉苹果树

混江龙づ霸主 提交于 2019-12-06 19:17:49
题目链接: 传送门 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100)。 N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。 每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过30000个。 输出格式: 一个数,最多能留住的苹果的数量。 输入样例 5 2 1 3 1 1 4 10 2 3 20 3 5 20 输出样例 21 首先,题目中说了,这是颗二叉树 有什么用呢? 没什么用 其实这会让题目变得没有那么复杂,一个节点只有左右两个儿子,存图和遍历的时候就多了一种方式 这是树形背包的经典题 然后我们开始设dp数组 设 f [ i ] [ j ] f[i][j] f [ i ] [ j ] 表示以 i i i 节点为根的子树保留 j j j 条边时保留下来的最大苹果数量 为什么这样设呢? 当然是看你的悟性。 如何看转移 f [ f r ] [ j ]

洛谷2015 二叉苹果树 树形DP

左心房为你撑大大i 提交于 2019-12-06 19:15:18
https://www.luogu.org/problemnew/show/P2015 二叉苹果树 时间限制: 1 Sec 内存限制: 128 MB 题目描述 有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点) 这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为 1 - N 树根编号一定是 1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一棵有 4 个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 输入 输入包含多组测试数据。 对于每一组测试样例: 第 1 行有 2 个数,N 和 Q(1 <= Q <= N,1 < N <= 100)。 N 表示树的结点数,Q 表示要保留的树枝数量。接下来 N-1 行描述树枝的信息。 每行 3 个整数,前两个是它连接的结点的编号。第 3 个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过 30000 个。 输出 一个数,最多能留住的苹果的数量。 样例输入 5 2 1 3 1 1 4 10 2 3 20 3 5 20 样例输出 21 分析: 状态表示:dp[i][j]表示子树i,保留j个节点的最大权值 每条边的权值,可以看作是儿子的权值,那么就可以对所有的子树做分组背包

[Luogu2015] 二叉苹果树 [树形dp]

扶醉桌前 提交于 2019-12-06 19:14:32
[ L i n k \frak{Link} L i n k ] 感觉自己在理清码代码思路上面还是有很大的不足 用树形 dp 练习一下。 我就卜把这题当作二叉树,直接套背包啦 记 f(x, c) ,表示以 x 为根的子树保留 c 条枝最多能够留下多少苹果。 那么,分类讨论: 对于某个点把它保留的 c 条枝头分别分给它的每个子节点 也就是说让每个子节点用一定的价值给父亲一定的贡献。 价值怎么分配?? 这个问题有一点点模糊,不过它实际上是一个很熟悉的模型 相当于 某个子节点可以任取代价,某个代价可以得到某种价值 这是多重背包的经典模型。 进一步考虑,化为直观的状态和方程。 题目要求是选一个点子树中的点那么这个点必须没有被剪 于是 f(x,c) = max{f(x,k)+Σf(child i ,x i )+val(edge)}, Σx i =c-k-1 至于不保留这个点的情况就是 f(x,0) ,会被父亲考虑到 因为根节点一定会被选(剪不掉),所以这样设计状态正好合适。 # include <cstdio> # include <iostream> # include <algorithm> # include <cstdlib> # include <cstring> # include <cmath> # include <cctype> # include <ctime> using

[SDOI2017]苹果树 题解

可紊 提交于 2019-11-29 12:32:13
首先,观察题意,可以发现在最长链下再接一个点,结果一定更优。 也就是说,可以免费选一条最长链,之后正常选。 我们枚举选的最长链,然后算出剩下部分的最优解。 有4部分: 1、链上每个点都选一个。 2、链上剩下的部分。 3、链的左面。 4、链的右面。 1可以直接计算。 那么,我们需要先进行树形背包,然后再通过某方式将其余3个合并。 我们知道,在此问题中,合并2个背包是 \(O(k)\) 的; 但3个及以上则是 \(O(k^2)\) 的,无法承受。 所以,我们只能在计算中就把其中两个合并,这样就只需合并2个了。 可以发现,3和4是正常的树形背包,而2是一个贪心的问题。 但是,我们没有时间给链上的点排序,再贪心选择。 所以,只能将2转为正常的树形背包问题。 可以这样想:选x则要选fx,选x的第二个则要选x的第一个。 那么,我们可以把大于1的拆点,拆成1和a-1。连上父子关系。 不难发现,这样我们就只需要3,4两个合并了。 先考虑如何进行树形背包: 来源: https://www.cnblogs.com/lnzwz/p/11517807.html