牛客訓練,殺樹,樹形dp

2021-10-06 05:08:24 字數 1465 閱讀 7415

一道樹形dp題,我剛開始想的是dp[

i][j

]dp[i][j]

dp[i][

j]表示i為根結點最長鏈的長度為j的最小代價,轉移的時候很複雜,最後還是沒寫出來(也有可能是寫炸了,但是這個狀態應該也是可以的)。比賽結束後看到題解是用dp[

i][j

]dp[i][j]

dp[i][

j]表示i為根結點最長鏈的長度小於等於j的最小代價,這樣轉移起來就很輕鬆了,所以做dp的時候選好狀態真的很重要…

首先遞迴,讓子節點的值全部更新完成。再更新當前結點的值。

遞推式:

當前結點刪除:當前代價加所有(子節點的最小代價)的和

d p[

now]

[0]=

a[no

w]+∑

s=so

n(no

w)dp

[s][

l−1]

dp[now][0]=a[now]+\sum_

dp[now

][0]

=a[n

ow]+

∑s=s

on(n

ow)​

dp[s

][l−

1]當前結點不刪:注意以now為根的樹的直徑要小於l

一般的dp[

now]

[i]=

∑s=s

on(n

ow)d

p[s]

[min

(i−1

)]

)dp[now][i]=\sum_dp[s][min(i-1)])

dp[now

][i]

=∑s=

son(

now)

​dp[

s][m

in(i

−1)]

)對於直徑大於l的:只能最多取乙個子節點長度為i-1其餘取l-i-1保證直徑在l以下!

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

inline ll read()

while(cc>='0'&&cc<='9')

return kk*f;

}const ll maxn=5055;

ll n,l,a[maxn],dp[maxn][maxn];

vectoredge[maxn];

void add(int a,int b)

void dfs(int now,int fa)

dp[now][i]=min(dp[now][i],dp[now][i-1]);//保證dp[i][j]表示<=j }}

int main()

黑白樹(牛客網 樹形dp)

題目描述 一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i...

牛客網 黑白樹(樹形dp)

一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i 的點都會...

牛客 路徑計數機 (樹形dp 字首和)

有一棵n個點的樹和兩個整數p,q,求滿足以下條件的四元組 a,b,c,d 的個數 1.1 leq a,b,c,d leq n 2.點a到點b的經過的邊數為p。3.點c到點d的經過的邊數為q。4.不存在乙個點,它既在點a到點b的路徑上,又在點c到點d的路徑上。第一行三個整數n,p,q。接下來n 1行,...