P2015 二叉蘋果樹 樹形動規

2022-04-30 10:12:09 字數 1458 閱讀 3668

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉(就是說沒有只有1個兒子的結點)

這棵樹共有n個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是1。

我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹

2   5

\ /

3 4

\ /1

現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋果。

給定需要保留的樹枝數量,求出最多能留住多少蘋果。

輸入格式:

第1行2個數,n和q(1<=q<= n,1n表示樹的結點數,q表示要保留的樹枝數量。接下來n-1行描述樹枝的資訊。

每行3個整數,前兩個是它連線的結點的編號。第3個數是這根樹枝上蘋果的數量。

每根樹枝上的蘋果不超過30000個。

輸出格式: 

乙個數,最多能留住的蘋果的數量。

輸入樣例#1: 

5 2

1 3 1

1 4 10

2 3 20

3 5 20

輸出樣例#1: 

21

一道我想了比較久的樹形dp.

本來以為就是常規的和選課差不多的基本樹形dp.

於是想出來乙個思路:

f [i][j] 表示當前以當前這個節點為根的子樹,刪掉了 j 條邊的最大值.

然後我想的是先預處理每乙個節點的邊之和和果子之和,結果發現妥妥的後效性...

於是,想到常規思路.不過為了取消對於當前這個邊是否為當前這個子樹的根的連邊的考慮.

f [i][j] 表示當前這個節點一定被儲存下來.

然後的話狀態轉移也就很簡單了,就是乙個類似於揹包的轉移方程.

但是,我打的時候,之前一直是 0 . 

結果發現,我對已經初始化了的 f[x][1],仍然進行了更新...

#includeusing

namespace

std;

const

int maxn=105

;struct

sja[maxn*2

];int

size,head[maxn];

intc[maxn],n,m,num[maxn];

intf[maxn][maxn],v[maxn];

void add(int x,int y,int

z)/*

void pre(int x)

}}*/

//沒卵用的初始化.

void dp(int

x) }

}int

main()

add(

0,1,0

); pre(0);

//memset(f,-1,sizeof(f));

dp(0

); cout

<1][m]<}

P2015 二叉蘋果樹(樹形dp)

題目傳送門 description 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 34 1現在這顆樹枝條太多...

P2015 二叉蘋果樹

這道題的dp還是先更新子節點,在更新父節點,不過問題就是怎樣更新他們 我們定義ff i j 為第i個節點字數上共保留j條邊的情況下最多的蘋果數,對於每乙個點,他保留的邊必然是他直接保留的之前保留的邊和他當前兒子保留的邊的值的和加上這一條邊的 邊權,即ff u i max ff u i f u i j...

P2015 二叉蘋果樹

題面 設f u i 表示u的子樹上保留i條邊,至多保留的蘋果數目 那麼狀態轉移方程也就顯而易見了 f u i max f u i f u i j 1 f v j e i w 1 i min q,sz u 0 j min sz v i 1 u表示當前節點,v是u的乙個子節點,sz u 表示u的子樹上的...