苹果树

二叉苹果树(由根分为左子树和右子树两部分情况)

岁酱吖の 提交于 2019-11-28 23:47:10
有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 个节点,标号 至 ,树根编号一定为 。 我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果。 输入格式 第一行两个数 N 和 Q ,N 表示树的节点数, Q表示要保留的树枝数量。 接下来 N-1 行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。 输出格式 输出仅一行,表示最多能留住的苹果的数量。 f[i][j]表示当前节点保留j根树枝的最大苹果数 #include<bits/stdc++.h> #define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=105; int n

洛谷 2015 二叉苹果树

走远了吗. 提交于 2019-11-28 13:50:11
原题链接: https://www.luogu.org/problem/P2015 题意就是给你n-1条树枝,每条树枝上都带有一定的苹果,问最后留下m根树枝,能拥有的苹果的最大值,根节点为1,每个节点只有2种情况,有2个儿子,或没有儿子。 这题是一个很典型的树形结构,因为节点以边相连,又为二叉结构,无环。我们这时候从根节点下顺,找到最深的儿子,然后一步步开始回溯,以当前回溯到的这个点作为根,考虑他 有几条边的最大值。那从下至上递推回去,根节点的状态只与2个子节点有关,很明显,这就是一个dp,且是树形的。 本题的状态转移方程要先列出: dp[i][j]=max{ dp[i][j],dp[i][j-k-1]+dp[son[i]][k]+val[i][son[i]] }(0<=j<=m,0<=k<j) .接下来解释这个方程从何而来。 以样例为例,我们这时候从根节点1向下搜索,找到了2,可是2这时候作为单点,并不存在边,便回溯,到3,这时候3-2有一条边,我们可以考虑是否要添这条边,dp[3][1]这时候要由dp[2][0] 转移而来,为什么呢,因为这时候3如果要与2相连,是肯定要加3-2这条边,不然子树与根就无法连接起来了吧。接下来查到5这个点回溯,可以处理dp[3][2]了,dp[3][2]只由dp[5][0]和dp[5][1]而来, 因为3-2处理过了对吧,由dp[5][1

P2015 二叉苹果树[树形dp+背包]

瘦欲@ 提交于 2019-11-28 06:16:57
题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。 解析 一道很简单的树形dp, 然而我调了半天都没调出来,就是菜 。 容易看出状态 \(dp[x][i]\) 表示以 \(x\) 为根的子树保留 \(i\) 条边能留住的最多苹果数。 这题坑点在于,题面其实没讲清楚,实际上我们要找的是 剪枝后使得剩下的树枝都能与根节点相连 的最优情况。 所以说,我们要在状态转移时体现出这一点。具体来说,就是每次转移我们都要保留至少一条从该根节点到其某个儿子的边。剩下的就是个分组多重背包,没什么好讲的。 状态转移: \[ dp[x][i]=\max\limits_{y\in tree(x),0<i<=min(size[x],q),0<=j<=min(size[y],i-1)}(dp[x][i],dp[x][i-j-1]+dp[y][j]+v(x,y).edge) \] 具体解释一下方程含义:首先显然,每个以 \(x\) 为根的子树能够保留的最多的边数就是其子树大小 \(

luogu2015 二叉苹果树

江枫思渺然 提交于 2019-11-27 08:38:05
题目 【题目描述】 有一棵苹果树,如果树枝有分叉,一定是分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个。 【输出格式】 一个数,最多能留住的苹果的数量。 【代码】 /* User:Mandy.H.Y Language:c++ Problem:appletree */ #include<bits/stdc++.h> #define Max(x,y) (x)>(y)?(x):(y) #define Min(x,y) (x)<(y)?(x):(y) #define mem(A) memset((A),0,sizeof(A)) const int maxn=102; int n,q,first[maxn],size=0,f[maxn]

【洛谷 2015】二叉苹果树

孤者浪人 提交于 2019-11-26 17:47:06
题目描述 有一棵苹果树,如果树枝有分叉,一定是分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,代码里写了注释哦,详见一本通哈哈。 #include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int N=102; int x,y

DP-树形DP-luogu2015-二叉苹果树

此生再无相见时 提交于 2019-11-26 05:34:39
题目大意 一棵 二叉 苹果树, 边 上结了苹果需要砍去一些边,求 保留 q条边时最多能保留多少苹果。(1<=n,q<=100) 2 5 \ / 3 4 \ / 1 问题分析 题目保证了原始苹果树有分叉则 必为二叉 ,且 1为root 注意 输入时父子顺序是不确定的 ,所以需要做处理 定义 d p i , j dp_{i,j} d p i , j ​ 表示编号为i的子树在 保留j条边 的情况下获得的最大苹果数目,则状态转移为 d p i , j = m a x { d p l c , k + d p r c , j − k − 2 + a p p l e l c + a p p l e r c d p l c , j − 1 + a p p l e l c d p r c , j − 1 + a p p l e r c dp_{i,j} = max \begin{cases} dp_{lc,k} + dp_{rc,j-k-2} + apple_{lc} + apple_{rc} \\ dp_{lc, j-1} + apple_{lc} \\ dp_{rc,j-1} + apple_{rc} \\ \end{cases} d p i , j ​ = m a x ⎩ ⎪ ⎨ ⎪ ⎧ ​ d p l c , k ​ + d p r c , j − k − 2 ​ + a p p l e l