SDOI2017 蘋果樹(揹包dp)

2021-09-10 18:12:20 字數 3194 閱讀 9726

題目鏈結

樹上依賴多重揹包,允許從根出發的一條鏈中每個點上的乙個物品免費,求最大價值。

揹包神仙題……

首先都能想到的就是列舉某個節點,這個節點到根上的所有節點使用一次免費的機會,那麼整棵樹就被分成了三部分:

1.這條鏈上所有點剩餘物品數量為ai−

1a_i-1

ai​−1;

2.這條鏈左邊所有點不變。

3.這條鏈右邊所有點不變。

於是這裡可以按照dfs序來dp,f[i

][j]

f[i][j]

f[i][j

]表示dp到了第i個節點,選了j

jj個節點達到的最大價值。從子樹更新上來的時候由於要強制必選乙個點,因此每個點物品的上界應該是ai−

1a_i-1

ai​−

1而不是a

ia_i

ai​,這樣最後必選的那條鏈也剛好可以保證剩餘物品數量為ai−

1a_i-1

ai​−1。

接下來翻轉所有節點掛的兒子順序,再做一遍上面的dp,只是要在dp完所有兒子之後再計算自己的貢獻。這個dp記為g[i

][j]

g[i][j]

g[i][j

],最後實際上就是求max

⁡\max\

max。因此複雜度為o(n

k)

o(nk)

o(nk)。

#include

namespace iostream

template

<

typename t>

inline

void

read

(t &x)

template

<

typename t1,

typename..

.t2>

inline

void

read

(t1 &a, t2 &..

.x)inline

intreads

(char

*s)inline

void

ioflush()

inline

void

printc

(char c)

inline

void

prints

(char

*s)template

<

typename t>

inline

void

print

(t x,

char c =

'\n'

)else

printc

('0');

printc

(c);

}template

<

typename t1,

typename..

.t2>

inline

void

print

(t1 x, t2.

.. y)

}using

namespace iostream;

using

namespace std;

typedef

long

long ll;

const

int maxn =

20005

, maxk =

26000005

, maxm =

500005

;struct edge edge[maxn]

;int head[maxn]

, lim[maxn]

, val[maxn]

, sum[maxn]

, temp[maxm]

, tot, n, m, t;

int poolf[maxk]

, poolg[maxk],*

(f[maxn]),

*(g[maxn]

), par[maxn]

;void

addedge

(int u,

int v)

; head[u]

= tot;

}int que[maxm]

, ans;

void

dfs1

(int u,

int fa)

for(

int i = head[u]

; i; i = edge[i]

.next)

}void

dfs2

(int u,

int fa)if(

!head[u]

)for

(int i =

0; i <= m; i++

) ans =

max(ans, f[u]

[i]+ sum[u]

+ g[u]

[m - i]);

for(

int i =

0; i <= m; i++

) temp[i]

= g[u]

[i];

int*he = que +1,

*ta = que;

for(

int i =

0; i <= m; i++)}

intmain()

memset

(poolf,0,

sizeof

(poolf));

memset

(poolg,0,

sizeof

(poolg));

f[0]

= poolf, g[0]

= poolg;

for(

int i =

1; i <= n; i++

)dfs1(1

,0);

memset

(head,0,

sizeof

(head)

); tot =0;

for(

int i = n; i >

0; i--

)addedge

(par[i]

, i)

;dfs2(1

,0);

print

(ans);}

ioflush()

;return0;

}

樹形揹包 蘋果樹

題目大意 求乙個聯通點集點權和 m leq m m的最大點的個數。這道題是乙個樹形揹包問題,以點的個數為體積,以體積為價值 然後我們只要找到體積 m le m m的最大點數即可。我們設f i j f i j f i j 表示以i ii為根的子樹中,一定選第i ii個點且選了j jj個點的最小花費。若...

二叉蘋果樹 樹型DP 揹包

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

二叉蘋果樹 樹形DP

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