uvalive4015 (樹上揹包)

2022-08-24 20:51:07 字數 1557 閱讀 2877

給一棵樹,邊上有權值,然後給乙個權值x,問從根結點出發, 走不超過x的距離,最多能經過多少個結點。

走過的點可以重複走,所以可以從乙個分支走下去,然後走回來,然後再走另乙個分支

dp[u][j][0] 表示從u出發,走了j個點,然後不回到u點的最小花費

dp[u][j][1] 表示從u出發,走了j個點,然後回到u點的最小花費

dp[u][j][0] = min(dp[u][j][0], dp[v][k][0]+dp[u][j-k][1]+dis, dp[v][k][1]+dp[u][j-k][0]+2*dis);

可能是當前這個分支不回到u點,那麼就是dp[v][k][0] + dp[u][j-k][1] +dis

可能是當前這個分支回到u點(那麼u->v的邊走兩次,那麼就是2*dis),但是以前的分支不回到u點,dp[v][k][1] + dp[u][j-k][0] + 2*dis

dp[u][j][1] = min(dp[u][j][1], dp[v][k][1]+ dp[u][j-k][1] + dis)

#pragma warning(disable:4996)

#pragma comment(linker, "/stack:1024000000,1024000000")#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

const

int inf = 1

<< 30;/*

樹形揹包

*/const

int n = 500 + 10

;struct

edge

g[n*2

];int

head[n], e, fa[n];

int dp[n][n][2

];int

size[n];

int n, u, v, dis, query[1111

];void addedge(int u, int v, int

dis)

void

init()

void dfs(int u, int

fa)

}}int

main()

introot;

for (int i = 0;i < n;++i)

if (fa[i] == -1

) root =i;

intq, x;

dfs(root, -1

); scanf("%d

", &q);

printf(

"case %d:\n

", tcase++);

while (q--)

}return0;

}

LA 4015 樹形揹包

題意 給一棵樹,每條邊上有一些權值,求 長度不超過 x 最多能走多少個點 分析 考慮每乙個節點,他可以一直走下去,也可以走回來而走到他的兄弟節點 狀態定義 d x j 0 1 從 i 出發,走 j 個節點的最短距離 1 回來,這就是乙個揹包,更新當前節點 2 不回來,則是要考慮從哪個部分不回來 1 ...

樹上揹包練習

p2014 ctsc1997 選課 p2014 ctsc1997 選課 solution 樹上揹包模板題 因為有多節課是沒有先修課的,所以並不是只有一棵樹,用乙個0號點作為沒有先修課的課程的先修課,這樣就合併成了一棵樹,只要選取m 1個點 必選0 即可。轉移方程 dp u j max dp u j ...

重建道路 樹上揹包

初始化 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 ...