luogu P2015 二叉蘋果樹

2022-03-27 07:14:13 字數 1935 閱讀 1681

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

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

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

2        5

3   4

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

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

輸入格式:

第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
樹上的揹包問題,很容易就想到如果刪除乙個子節點,那麼以這個節點的棵子樹就會全部刪除,那麼對這個子樹刪除的節點就不能超過子節點個數。

所以我們先dfs一邊,求出有多少乙個節點有多少子節點,並標記處father,保證不會到father

f[i][j]《在i這個子樹中刪除j個邊的最大值,然後貪心維護最大就好了

#include#include

#include

#include

#include

#define ll long long

using

namespace

std;

const

int maxn=150

;int

read()

while('0'

<=ch&&ch<='9')

return f*an;

}int

f[maxn],dp[maxn][maxn],cnt,fa[maxn],son[maxn],q,n;

bool

vis[maxn],vis2[maxn];

struct

saberb[maxn

<<1

];void add(int x,int y,int

z)void dfs(int

x) }

}void dp(int

x) }

}int

main()

dfs(1);

dp(1);

cout

<1

][q];

return0;

}

by:s_a_b_e_r

樓上一直堅持兩遍dfs,其實一遍就好了啊qwq

而且既然只向下dp,存單向邊就可以啦(但是要存一下father)

因為是二叉樹所以非常好辦

如果點x的子樹一共要保留i根樹枝

肯定是一部分(j)分給左子樹,剩下的(i-j)給右子樹

於是就可以愉快地填表dp了^_^

#include#include

using

namespace

std;

const

int n=109

;int

n,q,p[n],fa[n],f[n][n],cnt,son[n];

struct

edgee[n

<<1

];void add(int u,int v,int

w)void dfs(intu)}

intmain()

else

}dfs(1);

cout

<1][q]<

return0;

}

by:wypx

Luogu P2015 二叉蘋果樹

題目描述 有一棵蘋果樹,如果樹枝有分叉,一定是分2叉 就是說沒有只有1個兒子的結點 這棵樹共有n個結點 葉子點或者樹枝分叉點 編號為1 n,樹根編號一定是1。我們用一根樹枝兩端連線的結點的編號來描述一根樹枝的位置。下面是一顆有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 我既考慮子樹的左叉...