DP起手練習7 有用的樹規簡單基礎

2021-10-08 14:58:52 字數 1831 閱讀 8353

所謂樹規,簡單來說就是在樹這個結構上做普通dp.它所考慮的東西只比普通dp多兩點:建圖和遍歷.

我個人比較喜歡用鄰接表存圖,然後鏈式前向星和鄰接矩陣等憑個人愛好選擇;而遍歷往往只有兩種:根到葉子節點和葉子到根節點,一般後者使用比較廣泛,而實現用遞迴即可.

接下來思考這道題

(由於只是dp乙個基礎題,所以還是只給傳送門吧):

這道題很容易想到每個人只有兩種狀態:去和不去.

所以我們用f[i

][1]

f[i][1

]和f[i]

[0]f[

i][0

]分別表示第i

i個人去和不去時的ta與ta的所有下屬的快樂度總值,最後後答案即:

a ns

=max

(f[r

oot]

[0],

f[ro

ot][

1])(

root

為根節點

)an

s=ma

x(f[

root

][0]

,f[r

oot]

[1])

(roo

t為根節

點)進行進一步分析,我們發現:

若節點u選擇去,那麼它的子節點v只能不去,然後有dp轉移方程:

f [u

][0]

=f[u

][0]

+f[v

][0]

f[u][0

]=f[

u][0

]+f[

v][0

];若節點u選擇不去,那它的子節點v可去可不去,然後有dp轉移方程:

f [u

][1]

=f[u

][0]

+max

(f[v

][0]

,f[v

][1]

)f[

u][1

]=f[

u][0

]+ma

x(f[

v][0

],f[

v][1

]);解決完dp後我們再來解決樹的問題:先用鄰接錶連邊(由根->葉),

統計每個點的入度,再掃瞄一次,若掃到乙個節點入度為0,那這個節點就為根節點,最後由根開始dfs一遍更新答案即可.

#include

#define n 6003

using

namespace std;

int n,tot,ans,root;

int a[n]

,f[n][2

],fi[

2*n]

,nxt[

2*n]

,to[

2*n]

;bool rd[n]

;inline

void

lian

(int u,

int v)

//鄰接表

inline

void

dfs(

int u)

return;}

intmain()

for(

int i=

1;i<=n;i++

)//尋根

}dfs

(root)

;//從根開始

ans=

max(f[root][0

],f[root][1

]);printf

("%d\n"

,ans)

;return0;

}

以上為個人見解,望本篇部落格對各位有所幫助.

DP 樹形 DP 樹的中心

做法 a 大致想法是進行兩遍dfs,找到每個節點的向下的最長路徑 di 和向上的最長路徑 ui 然後列舉每乙個點,再找到min max di ui b 補充細節 1 根據樹的直徑求法,向下求的時候會有乙個最大值和次大值,例如節點 i 的 d1i d2i,當更新 i 的某個子節點 j 的 uj 時候,...

DP練習 奶牛的鍛鍊

奶牛bessie有n分鐘時間跑步,每分鐘她可以跑步或者休息。若她在第i分鐘跑步,可以跑出d i公尺,同時疲倦程度增加1 初始為0 若她在第i分鐘休息,則疲倦程度減少1。無論何時,疲倦程度都不能超過m。另外,一旦她開始休息,只有當疲憊程度減為0時才能重新開始跑步。在第n分鐘後,她的疲倦程度必須為0。第...

樹形dp 樹的重心

1.只需要求出最大子樹中節點數最小的數目即可 題意 有乙個國王要把他的領土分給兩個兒子,國王的領土是一棵樹,n個結點,n 1條邊把這些結點連起來,現在大小兒子要選擇乙個點作為他的首都,那麼除首都分別是這兩個兒子之外,其他的城市 結點 根據離誰近就歸誰所有,如果一樣遠的話就歸大兒子所有,現在假設兩個人...