樹上揹包練習

2021-10-08 02:05:23 字數 2107 閱讀 2563

p2014 [ctsc1997]選課

p2014 [ctsc1997]選課

solution

樹上揹包模板題

因為有多節課是沒有先修課的,所以並不是只有一棵樹,用乙個0號點作為沒有先修課的課程的先修課,這樣就合併成了一棵樹,只要選取m+1個點(必選0)即可。

轉移方程: dp[u][j] = max(dp[u][j - k] + dp[v][k],dp[u][j]);

01揹包,所以j要倒序列舉

**

#include

using

namespace std;

const

int sz =

320;

typedef

long

long ll;

int n,m,fist[sz]

,temp;

int dp[sz]

[sz]

,b[sz]

,a;//dp[i][j] 為在i為根的子樹上選擇j個節點的最大學分

struct zt

line[sz]

;inline

void

add(

int a,

int b)

; fist[a]

= temp;

}inline

intdfs

(int u)

}int

main()

dfs(0)

;printf

("%d\n"

,dp[0]

[m])

;return0;

}

p1273 有線電視網

p1273 有線電視網

solution

與上題類似,改為只選葉子節點,同時減去邊的花費。

令dp[i][j]為以i為根的子樹中選擇j個葉子節點的最大收益。

轉移方程:dp[u][j] = max(dp[u][j],dp[u][j - k] + dp[v][k] - line[i].w)

最終結果可能是負值,所以dp陣列初始化為乙個極小值。

**

#include

using

namespace std;

const

int sz =

3000+20

;const

int inf =

0x3f3f3f3f

;typedef

long

long ll;

int n,m,fist[sz]

,val[sz]

,temp,dp[sz]

[sz]

;struct zt

line[sz]

;inline

void

add(

int x,

int y,

int z)

; fist[x]

= temp;

}inline

intdfs

(int u)

int sum =0;

// 當前節點為根時,子樹中葉子節點的數量

for(

int i = fist[u]

;i !=-1

;i = line[i]

.nxt)

return sum;

}int

main()

}for

(int i = n - m +

1;i <= n;i ++

)scanf

("%d"

,&val[i]);

for(

int i =

1;i <= n;i ++

) dp[i][0

]=0;

dfs(1)

;for

(int i = m;i >=

0;i --)}

return0;

}

2020.7.12

重建道路 樹上揹包

初始化 void init struct edges edge maxm 1 無向圖則需要乘2 inline void add int u,int v head u cnt int dp m m siz m tmp m int n,m void dfs int u,int fa siz u siz ...

樹上依賴揹包總結

做了很多關於樹上dp的題有些使用了nm 2的演算法來進行dp,可是當m過大時方法不大試用,又可以對這種演算法進行優化,如dfs序或者直接樹上合併揹包。當輸出方案時又需要多叉轉二叉進行dp尋找方案,很多方法於是乎總結一下。w i 表示第i個節點的重量,v i 表示第i個節點的價值,f i j 表示以i...

動態規劃 樹上揹包

題意 每個頂點有兩個權值b和w。最多3000個節點的樹,分成恰好m個非空的連通塊,使得盡可能多的連通塊滿足w的和嚴格大於b的和。樹上揹包的套路題,這裡揹包 dp i j 表示以i為根的子樹,已經劃分了 j 個連通塊,包括根節點在內的最後乙個連通塊沒有劃分,能取到的最優值。這一題最優值看起來有兩維,但...