洛谷P2015 二叉蘋果樹

2022-03-17 17:06:47 字數 2892 閱讀 6402

題目描述

有一棵蘋果樹,如果樹枝有分叉,一定是分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 21 3 1

1 4 10

2 3 20

3 5 20

輸出樣例#1

21演算法:

樹形dp

分析:

這道題其實是要我們計算在一棵二叉樹上保留一定數量的枝條情況下的最大權值。

這是乙個基礎的樹形dp模板題,在二叉樹上進行動規。我們發現對於樹上的任意一棵子樹,它的根節點和兩個子樹存在著關係,我們**一下,樹是由遞迴性質得到的,所以我們首先要把我們得到的資料先在乙個陣列上建造出來。

把樹建好了之後,我們就可以**它的狀態轉移方程,我們已知n-1條邊,為了方便,我們把它設為雙向的邊。我設len[x][y]和len[y][x]表示x到y的邊上權值為len[x][y](或len[y][x])。

接下來,設num[v]表示以v為子節點的那條邊的長度,設f[v][k]為以v為根節點的子樹中保留k條邊的最大權值,設tr[v][ans]為以v為根節點的左右兒子分別是什麼,當ans表示1時,他是左兒子,反之,則為右兒子。

把一棵樹放到乙個線性dp裡面想的話,就會容易多了。我要求當前的f[v][k],我首先要求得他的左右兒子分擔一共k條邊的最大值分別是什麼,然後相加即可。

可列得狀態轉移方程為:f[v][k]=max(f[v][k],f[tr[v][1]][i]+f[tr[v][2]][k-i-1]+num[v]);

這個東西相信不難看懂,接下來我們需要優化程式。既然樹可以遞迴來建造,那麼我們是不是也可以用遞迴來求解呢?嗯,是可以的。

這是我們就可以將普通的dp放到dfs上做,合成了記憶化搜尋。因為有一些枝條我在之前已經計算過了,那麼我可以直接拿來用。

說幾點注意的,最後輸出答案要輸出q+1的情況,因為在計算過程中我們為了方便,將邊的問題都轉化成父節點或者是子節點問題,所以需要我們在節點數上再+1。

切記len陣列要初始化乙個負數,在用完其中一條邊時,記得把那條邊和另外一條等價的邊都給刪掉。

上**:

1 #include2 #include3

using

namespace

std;45

int n,q,tr[110][3],num[110],len[110][110],f[110][110]; //

資料規模不大,int 型已經足夠

67 inline int read() //

讀入優化817

18void buildtree(int v) //

建樹1932}

3334

void dfs(int v,int k) //

記憶化搜尋

3553}54

}5556int

main()

5769 buildtree(1); //

建樹70 dfs(1,q+1); //

求解71 printf("

%d",f[1][q+1]); //

注意,切記是q+1

72return0;

73 }

這是一道二叉樹的基礎dp,我感覺挺好理解的,主要的模型就是遞迴建樹+記憶化搜尋dp,簡單記為2個dfs。

嗯,就這樣了。

洛谷 P2015 二叉蘋果樹

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

洛谷P2015 二叉蘋果樹

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1 現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有...

洛谷P2015 二叉蘋果樹

有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有4個樹枝的樹 2 5 3 4 1現在這顆樹枝條太多了,需要剪枝。但是一些樹枝上長有蘋...