洛谷P2015 二叉蘋果樹 樹形dp)

2021-10-03 21:58:14 字數 1660 閱讀 4944

題目描述

有一棵蘋果樹,如果樹枝有分叉,一定是分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現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果...