樹形DP簡介

2021-08-07 04:51:53 字數 1394 閱讀 1663

樹形dp就是在「樹」的資料結構上做動態規劃,通過有限次地遍歷樹,記錄相關資訊,以求解問題。樹形dp有根到葉(常見)葉到根兩個方向,就是將父親結點的資訊向下傳遞給子結點,或者從子結點向上傳遞資訊給父親結點。

因為樹本身至少就有「子結構」性質(樹和子樹);也本身就具有遞迴性。所以在樹上dp其實是其所當然的事,相比線性動態規劃來講,轉移方程更直觀,更易理解。

有n個人,接下來n行是n個人的價值,再接下來n行給出l,k,說的是l的上司是k。要求l與k不能同時出現,求最大的結點價值和。

dp[rt][1]+=dp[g[rt][i]][0];

dp[rt][0]+=max(dp[g[rt][i]][1],dp[g[rt][i]][0]);

//g[rt][i]為當前根節點可以到達的孩子

此類題目的關鍵在於建樹,建樹的方法也有多種:

可以用鏈式結構,可以用下面**示例中的二維動態陣列(相當於鍊錶)

也可以用鏈式向前星(優化空間,以我目前的經驗是比vector稍快),但沒有普通的鄰接表好寫

有的題目甚至不需要建樹,只需邊遍歷邊遞推

建好樹又有了轉移方程,其他的就不怕不怕了

#include

using

namespace

std;

int n;

const

int maxn=6005;

/*struct edgeedges[maxn];

*/vector

g[maxn];

int value[maxn];

int father[maxn];

int dp[maxn][2];

void dfs(int rt)

dp[rt][0]=0;

dp[rt][1]=value[rt];

for(int i=0;i1]+=dp[g[rt][i]][0];

dp[rt][0]+=max(dp[g[rt][i]][1],dp[g[rt][i]][0]);

}return ;

}void init()

}int main()

int u,v;

while(cin>>u>>v&&(u+v))

int root=1;

while(father[root])

dfs(root);

cout

<0],dp[root][1])0;}

樹形DP 樹形DP四例

是時候練一下dp了!我的題單 portkey f u,if fu,i 表示以u uu為根節點的子樹中保留i ii條樹枝的最大蘋果數 f u,i max f max f fu,i max這些題是菜,但也不能輕視啊!include using namespace std define in read i...

HLOJ 樹形DP前置 DFS(樹形DP入門)

給定一棵 n nn 個點的樹,根為 t tt求每個點的父親是哪個點,t tt 的父親輸出 0 00第一行兩個整數 n,t n,tn,t接下來 n 1 n 1n 1 行,每行兩個整數 x,y x,yx,y,表示 x,y x,yx,y 之間有一條邊 n nn 行,第 i ii 行乙個整數,表示 i ii...

樹形dp小結

這些天做了一些樹形dp的題目,感覺有了些領悟,尤其是理解到樹形揹包就是分組揹包之後。選出幾道不錯的總結一下 hdu 1520 hdu 4003 poj 1155 poj 2486 hdu 4313 hdu 4340 hdu 1520 入門水題 每個節點有權值,子節點和父節點不能同時選,問最後能選的最...