基礎演算法 二叉蘋果樹

2021-09-12 12:30:31 字數 1805 閱讀 1710

題目

描述 輸入

輸出樣例輸入

樣例輸出 分析

狀態轉移方程:

提出疑問 解答

**有一棵蘋果樹,如果樹枝有分叉,一定是分 2 叉(就是說沒有只有 1 個兒子的結點)。這棵樹共有 n 個結點(葉子點或者樹枝分叉點),編號為1-n,樹根編號一定是 1。 我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有 4 個樹枝的樹:

第1行: 2個空格分開的整數,n 和 q(1≤q≤n,1<n≤100),n表示樹的結點數,q表示要保留的樹枝數量。 接下來 n-1 行描述樹枝的資訊。 每行3 個整數,前兩個是它連線的結點的編號。第3 個數是這根樹枝上蘋果的數量。 每根樹枝上的蘋果不超過30000 個。

第1行:乙個整數,表示最多能留住的蘋果的數量。

5 2 

1 3 1

1 4 10

2 3 20

3 5 20

21
顯然易見的出自樹形dp板塊的樹形dp題

如圖,顯然答案為 1 - 3這條邊 + 3 - 2(3 - 5)這兩條邊之和

這道題相比於沒有上司的舞會

區別在於:只有選擇了他的父親,才能選擇他自己,其次,此題是限制了選擇個數的,似乎與選課

有幾分相似。

因而,我們可以定義狀態dp[i][j]表示在已 i 為根節點的子樹中選擇 j 條邊(或者 j 個頂點)所獲得的最大蘋果數。

我們就以樣例為例看看他是怎麼算出來的

dp[1][1] = max(g[1][4],g[1][3]);

dp[1][2] = max(g[1][4] + dp[4][1],g[1][3] + dp[3][1],g[1][4] + g[1][3]);

頗有揹包的意味,而且是 01 揹包!

為什麼是 dp[u][i - j - 1]呢

j 為什麼可以為0,又為什麼又要小於 i - 1呢

其實第乙個問題和第二個問題的第二問是一樣的。

因為從當前節點到他的兒子的那條路也是要被算上的(即g[u][v]),所以就需要從以他的兒子為根的子樹中選 i - j - 1條路徑。

對於第二個問題中的第一問

因為在計算dp[u][1]時,算的只是他到他的兒子中路徑的最大值,而選 0 條路徑的值必定是 0 了。

#include#include#define ll long long

#define m 100

#define reg register

#define min(a,b) (a > b ? b : a)

#define max(a,b) (a > b ? a : b)

using namespace std;

struct node

node(int to,int val)

};vector < node > g[m + 5];

int n,m,dp[m + 5][m + 5];

int dfs(int x,int fa)

return d;}

int main()

dfs(1,0);

printf("%d\n",dp[1][m]);

return 0;

}

二叉蘋果樹

我們可以把保留邊轉換成保留點 因為我個人對保留點熟 跟據樹的性質,乙個點有0or1個根。所以我們可以把邊上的蘋果數轉移到子節點上。根據題意可知這應是一道dp題 廢話 設f i j 為以i為根的樹上保留j個節點的最大權值和,又因為這是個二叉樹,所以我們不妨設左子樹要保留的節點數為k,那麼右子樹的需要保...

二叉蘋果樹

有一棵二叉樹,每條樹枝上有乙個權值,求保留 q 個樹枝下能達到的最大權值。我們考慮 n 較小,先把邊轉化為點,我們可以用 f i j 表示以 i 為根的子樹中選 j 個節點的能達到的最大權值,那麼有三種情況 1 左子樹全部砍掉。2 右子樹全部砍掉。3 左子樹保留 k 個,右子樹保留 j k 個節點,...

題解 二叉蘋果樹

question 題目大意 邊權版本樹形 dp 求保留 q 條邊,使得其邊權和最大。當然,必須聯通。要不就不是 dp 了 那考慮設計 dp i j 表示第 i 個節點,選擇 j 條邊的最佳方案。寫出方程為 dp i j max dp i j k dp v k e i dis 列舉 k 表示邊數。這有...