背景
题意
给定 (n) 个物品的依赖物品 (k_i) ( (k_i=0) 表示无依赖物品)及权值 (val_i) ,求选出 (m) 件物品的最大权值和。
解法
背包类树形 (dp) 模板。
考虑把所有依赖关系画在一张图上,显然是一个森林。不妨把每棵树的根都设定一个 (0) 号物品作为依赖物品,则整张图就变成了一棵以 (0) 为根节点的树了。
按照套路,设 (f_{x,t}) 表示以 (x) 节点为根的子树里选出了 (t) 件物品的最大权值和。假设当前节点 (x) 的儿子为 (y_1,y_2,y_3,cdots cdots,y_p) 共 (p) 个,则转移方程就是 (f_{x,t}=max_limits{ sum_limits{i in [1,p]} t_i=t-1} { sum_limits{i in [1,p]} f_{y_i,t_i} }+val_x) 。
考虑变形。这个转移本质上就是从 (p) 组每组都有 (t-1) 个物品的物品集合里每组选出一个物品,一共选出 (t-1) 个。因此采用分组背包的转移即可。
注意 (x=0) 时并不需要选根节点(即此时可以选 (t) 个物品),于是先不做根节点 (dp) 值的更新,子树都更新完之后再根据 (x) 是否为 (0) 从 (f_{x,t-1}) 转移到 (f_x) 即可。
另外,由于这是一个分组背包,每件物品只能用一次,所以循环体积的时候要倒序枚举。又因为有体积为 (0) 的物品,所以对于组内物品的枚举也需要倒序。
细节
对于给定依赖关系的处理,由于 (k_i=0) 表示无依赖物品,而我们也正好设定一个 (0) 号物品作为依赖物品,于是它的处理与其他的处理没有任何区别,直接在被依赖物品的儿子里加入依赖它的物品即可。