給一棵樹,邊上有權值,然後給乙個權值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 ...