題目描述
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)
這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。
我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹
2
5 \ /34
\ /1
現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。
給定需要保留的樹枝數量,求出最多能留住多少蘋果。
輸入格式
第1行2個數,n和q(1<=q<= n,1n表示樹的結點數,q表示要保留的樹枝數量。接下來n-1行描述樹枝的資訊。
每行3個整數,前兩個是它連線的結點的編號。第3個數是這根樹枝上蘋果的數量。
每根樹枝上的蘋果不超過30000個。
輸出格式
乙個數,最多能留住的蘋果的數量。
輸入輸出樣例
輸入 #1
5 21 3 1
1 4 10
2 3 20
3 5 20
輸出 #1
21solution
樹形dp。
設dp[i][j]為對於當前節點i選擇保留j條邊的最大蘋果數。
細節:原節點加子節點邊數之和為j - 1,因為要選擇改子樹,必須有一條邊連線原節點和子節點。
dp[i][j] = max(dp[i][j],dp[i][j - 1 - k] + dp[v][k] + node[i].w)
( 1<= j <= min(m,i的子節點數) )
( 0 <= k <= min(j - 1,v的子節點數) )
考慮決策方向:類似於01揹包,選不選擇當前子樹,獲得的價值是蘋果數,每次花費選邊的次數。故應該倒序列舉j,防止重複選擇子樹。
**
#include
#include
#include
#include
#include
using
namespace std;
typedef
long
long ll;
const
int sz =
100+5;
struct zt
node[sz <<1]
;int temp,fist[sz]
,n,m,sz[sz]
;int dp[sz]
[sz]
;inline
void
build
(int x,
int y,
int z)
inline
void
dfs(
int u,
int fa)}}
intmain()
dfs(1,
-1);
printf
("%d\n"
,dp[1]
[m])
;return0;
}
2020.3.15 洛谷 P2015 二叉蘋果樹 樹形dp
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...
洛谷P2015 二叉蘋果樹(樹形dp)
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...
洛谷P2015 二叉蘋果樹 樹形DP
有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 34 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果...