Luogu P2015 二叉蘋果樹

2021-09-02 22:46:29 字數 2084 閱讀 8740

題目描述

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

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

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

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

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

輸入格式:

第1行2個數,n和q(1<=q<= n,1輸出格式:

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

輸入樣例

5 21 3 1

1 4 10

2 3 20

3 5 20

輸出樣例

首先,題目中說了,這是顆二叉樹

有什麼用呢?

沒什麼用

其實這會讓題目變得沒有那麼複雜,乙個節點只有左右兩個兒子,存圖和遍歷的時候就多了一種方式

這是樹形揹包的經典題

然後我們開始設dp陣列

設f [i

][j]

f[i][j]

f[i][j

]表示以i

ii節點為根的子樹保留j

jj條邊時保留下來的最大蘋果數量

為什麼這樣設呢?

當然是看你的悟性。

如何看轉移

f[f

r][j

]=ma

x(f[

fr][

j],f

[fr]

[j−k

−1]+

f[ca

][k]

+edg

e[i]

.dis

)f[fr][j] = max(f[fr][j], f[fr][j - k - 1] + f[ca][k] + edge[i].dis)

f[fr][

j]=m

ax(f

[fr]

[j],

f[fr

][j−

k−1]

+f[c

a][k

]+ed

ge[i

].di

s)

當前節點為frfr

fr現在遍歷到的節點為caca

ca在迴圈中我們枚舉子樹的邊數k

kk總邊數為j

jj所以子樹的價值為f[c

a][k

]f[ca][k]

f[ca][

k]因為還有frfr

fr到t oto

to這條邊所以邊數要再減1

11剩下的價值就是f[f

r][j

−k−1

]f[fr][j - k - 1]

f[fr][

j−k−

1]最後加上這一條邊上的蘋果就好了

**中還會有解釋

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define a 1000010

#define b 2010

#define ll long long

using

namespace std;

struct node edge[a]

;int head[a]

, num_edge;

void

add_edge

(int from,

int to,

int dis)

int f[b]

[b], n, q, a, b, c, size[a]

;void

dfs(

int fr,

int fa)

}int

main()

dfs(1,

0); cout << f[1]

[q];

}

luogu P2015 二叉蘋果樹

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

Luogu P2015 二叉蘋果樹

題目鏈結 樹上零一dp 記憶化搜尋 如果是空結點 如果是葉子結點直接返回蘋果數 以上都不滿足的話,dp狀態轉移 設定dp的轉移,轉移到左右兒子結點 for int i 1 i結果31分 1.說白了,記憶化搜尋還不是掌握的特別好 2.其次狀態設計不是特別好,在儲存左右兒子時,應該該需要儲存邊的 inc...

Luogu P2015二叉蘋果樹(DP,DFS)

題目鏈結 設f i j k 表示給以i為根節點的子樹分配j條可保留的樹枝名額的時候,狀態為k時能保留的最多蘋果。k有三種情況。k 1 我只考慮子樹的左叉,不考慮子樹的右叉,此時子樹能保留的最多的蘋果。k 2 我只考慮子樹的右叉,不考慮子樹的左叉,此時子樹能保留的最多的蘋果。k 3 我既考慮子樹的左叉...