( 動態規劃專題 ) 樹形dp

2021-10-02 12:08:54 字數 1394 閱讀 1962

( 動態規劃專題 )【 樹形dp 】

直接看例題:p2015 二叉蘋果樹

有一棵蘋果樹,如果樹枝有分叉,一定是分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
思路:

很明顯,這是乙個樹狀結構,我們可以從這點出發來考慮。這道題明確給出了根的位置,也就確定了父子節點的關係,我們會發現,對於每個父節點的狀態,都是由它的子節點轉移過來的,所以我們大概可以得出這裡有乙個由子節點轉移到父節點的狀態轉移方程,又因為父節點子樹上選擇的邊數完全取決於子節點的子樹選擇的邊數。

u表示當前節點,v是u的乙個子節點,sz[u]表示u的子樹上的邊數,q就是題目中要求的最多保留邊數

f[u][i] 表示以u為根節點的子樹選擇 i 條邊權值和最大為多少,這實際上就是乙個揹包。為什麼兩個f陣列的邊數為i−1條呢?因為我們若想取一顆子節點的子樹上的邊,那就必須取父節點與子節點相連的那條邊。

**:

#include using namespace std;

int n,m;

int dp[105][105];

int head[105],cnt;

int sz[105];

struct node e[105];

void addage( int u, int v, int w )

void dfs( int u, int fa )}}

}int main()

dfs(1,-1);

cout << dp[1][m] << endl;

return 0;

}

動態規劃專題(二) 樹形DP

dp 這東西真的是博大精深啊.樹形 dp 顧名思義,就是在樹上操作的 dp 一般可以用 f i 表示以編號為 i 的節點為根的子樹中的最優解。轉移的時候一般都將資訊由子節點轉移到父親節點,也就是將資訊從下往上轉移。因此,一般樹形 dp 都會採用遞迴的形式。樹形 dp 中有一種比較經典的題型 樹上揹包...

動態規劃 樹形DP

樹形dp,即在樹上進行的動態規劃,由於樹固有的遞迴性質,因此樹形dp往往也遞迴進行。某大學有 n nn 個職員,編號為 1.n1.n 1.n 他們之間有從屬關係,也就是說他們的關係就像一棵以校長為根的樹,父結點就是子結點的直接上司。現在有個周年慶宴會,宴會每邀請來乙個職員都會增加一定的快樂指數 r ...

動態規劃(dp)專題

航線設定 問題描述 在美麗的萊茵河畔,每邊都分布著n個城市,兩邊的城市都是唯一對應的友好城市,現需要在友好城市間開通航線以加強往來,但因為萊茵河常年大霧,如果開設的航線發生交叉就有可能出現碰船的現象。現在要求盡可能多地開通航線並且使航線不能相交。輸入有若干組測試資料,每組測試資料的第一行是乙個整數n...