多叉樹的樹形揹包常見建模方法

2021-09-07 14:39:35 字數 2516 閱讀 2926

多叉樹的樹形揹包常見建模方法 - csdn部落格

一.多叉樹變二叉樹。

這個技巧其實也有兩種具體的方法:樹的孩子兄弟表示法與dfs序法。

1.樹的孩子兄弟表示法。

總結成口訣就是:第乙個兒子是左子樹,其他兒子是左子樹的右子樹(似乎並不押韻,手動滑稽)

2.dfs序法

dfs序就是對乙個樹進行乙個dfs,然後對於每個點記錄乙個時間戳dfn陣列,這個時間戳就是這個節點的dfs序,然後我們再記錄乙個size陣列,表示以每個節點為根的子樹中節點的數量。

假設根節點是u,那麼可以容易的推出

第乙個兒子的dfs序dfn[first_son]就是dfn[u]+1

第二個兒子的dfs序dfn[second_son]就是dfn[u]+size[first_son]+1

其餘同理。

那麼u的下乙個兄弟的dfs序dfn[next_brother]就是dfn[u]+size[u]+1

這兩個方法大多用於樹形依賴形揹包(即使用乙個節點必須要使用它所有的祖先),

主要解決點權問題。

主要作用就是可以使決策轉移的過程變成o(1)的了。

最常見的模型就是:有n個物品,有乙個m大小的包,每個物品有wi物重與vi物品價值,物品之間存在只有裝了物品a,才能裝物品b的n-1條關係(就是乙個樹)。問能取得的最大價值。

簡要分析:顯然是乙個多叉樹,考慮轉換。

1.孩子兄弟表示法:對於乙個節點i,設dp[i][j]表示在以i為根的子樹中,用大小為j的包能取得的最大價值,那麼dp[i][j]=max(dp[left[i]][j-w[i]]+v[i],dp[right[i]][j])

注意,這裡的left[i]是i在原樹中的第乙個兒子,right[i]是i在原樹中的下乙個兄弟。

這個方程是非常好理解的。效率就是o(nm)的。

2.dfs序法:對於乙個dfs序為i的節點u,同樣設dp[i][j]表示在以u為根的子樹中,用大小為j的包能取得的最大價值,那麼dp[i][j]+v[i]->dp[i+1][j-w[i]]

dp[i][j]->dp[i+size[i]+1][j]

注意,這裡的轉移並不是常見的dp[i][j]=max()....(用dp[i][j]的前驅狀態去計算dp[i][j]),而是用dp[i][j]去更新它的後繼狀態。這種方法被稱為刷表法。

兩種方法都是非常巧妙的。但作用也是有限的,只能解決依賴性揹包中的點權問題。

二.分組的樹形揹包。

這類問題也是有乙個常見模型的,具體可參考洛谷p1272重建道路。

下面針對這道題來分析,能夠解決多叉樹的,分組的樹形揹包。

此時,我們的兒子與父親之間並不存在依賴型關係,那麼我們設dp[k][i][j]表示以i為根的子樹,在前k個兒子中,分離出乙個大小為j的子樹(必須包含i),所需要最少的操作次數。

那麼我們每計算到第k+1個新的兒子v時(full_son[v]表示v的兒子個數),

dp[k+1][i][j]=min(dp[k][i][j-t]+dp[full_son[v]][v][t]);

由於乙個樹形關係,我們需要在乙個dfs上進行dp,即先dfs(v),然後更新dp[k+1][i][j]。

這個k的一維顯然可以用滾動陣列優化掉。

那麼就是

j=m->1

t=1->j

dp[i][j]=min(dp[i][j-t]+dp[v][t]);

同時,dp一律要注意初始化,即剛開始時所有的dp[i][1]=du[i](du[i]表示與i連邊的節點數,又稱i的入度(樹是無向邊喲!))

1 #include2 #include3 #include4

using

namespace

std;

5const

int inf=0x3f3f3f3f;6

const

int n=201;7

struct

edgee[n*2

];10

intdu[n],a[n],dp[n][n];

11int n,k,res=inf,edgecnt=0;12

void addedge(int u,int

v)17

void dfs(int u,int

fa)27

}28 res=min(res,dp[u][k]);29}

30int

main()

40 dfs(1,0

);41 printf("%d"

,res);

42return0;

43 }

同樣,這個方法也是有缺陷的,就是無法解決點權問題。大多數運用於邊權問題。點權當然也可以,但是效率較低。

最後總結一句:樹形揹包都與dfs離不開關係,所以我們可以在dfs上dp可以寫的更簡單,也可以在dfs預處理後再總刷表法dp。

這三種方法都各有長處,各有短處,實際運用時還是要注意題目本身的。

cogs 1199選課(樹形dp 揹包或多叉轉二叉

題意 給m門課,每門課在上完其先修課後才能上,要你從中選n門課使得總學分盡可能大。思路 揹包,沒有先修課看成其先修課編號為0,求乙個f 0 n 的揹包,表示以0為根的樹選n個結點的最大總權值,設x為根,y為x的孩子,對每個孩子,dfs y 然後f x t max f x t f x t j f y ...

樹形dp技巧,多叉樹轉二叉樹

今天覆習樹形dp時發現一道比較古老的題,叫選課,是樹形dp的一道基礎題,也是多叉樹轉二叉樹應用的模版題 多叉樹轉二叉樹的應用非常廣泛,因為如果乙個節點的兒子太多,乙個乙個存下來不方便去查詢,並且會增加複雜度,但是這裡我們就有乙個o n 的複雜度的方法把多叉樹轉換為二叉樹,轉換成二叉樹後就更方便查詢,...

有依賴的揹包問題(樹形dp 揹包問題)

acwing 10.有 n 個物品和乙個容量是 v 的揹包。物品之間具有依賴關係,且依賴關係組成一棵樹的形狀。如果選擇乙個物品,則必須選擇它的父點。如下圖所示 如果選擇物品5,則必須選擇物品1和2。這是因為2是5的父節點,1是2的父節點。每件物品的編號是 i,體積是 vi,價值是 wi,依賴的父節點...