树形背包再总结

【前言】

哎,这几天被树形背包搞懵了,一开始感觉没学到啥,做一个题看一个题解,每个题单个来看都能看懂,但是遇到一个新题就不会了,而且你用上一个题的做法做,依旧不对,网上的题解有事五花八门,感觉还是每学透,有的时候二维的for需要到过来,有的时候就不用,不明白为什么,不想学树形DP不想那么稀里糊涂的过去,学一门就要搞懂他,这几天一直在看,发现背包也忘得差不多了,重新看了一遍背包九讲,补了补以前发的博客,虽然那个泛化背包不怎么会用,但树形背包,在今天终于看懂了,终于把所有做过的树形背包的题串起来了,明白了这个为什么能用这个方法,那个为什么不能用

回来还要填坑

【定义】

树形背包解决的问题是给你几个物品,但物品有依赖关系,a依赖b,b依赖c,选a就必须选b,选b就必须选c,一个物品只能依赖一个物品,但一个物品可以被多个物品依赖,这里就能看出来这是一个树。叫你选择n物品可以使得价值最大,价值为多少?

【以题入门】

做题的时候可以参照下面的建树过程

1.​​洛谷 P2014 选课​​ 

代码建议看第一个,第二个也可以看看,以后基本题目都是第一个的模型转变。虚结点的用法也特别妙。

2.​​洛谷 P2015 二叉苹果树​​

这题遇上题一模一样,但是这题目没给标准的给你父节点和子节点,但在后面给你一个价值,这时候你不确定子节点是谁,所以值不能想上一题一样直接复制子节点,所以vextor就不好入手了,需要建立双向的,所以建树时要注意。

其他不一样在题解报告已经给出

3.​​树形背包 POJ1155TELE​​

很简单一道题,状态方程稍微变一下,不过可以学到一个递归求u的子节点数量的方法。

4. ​​The more, The Better​​

根​​洛谷 P2014 选课​​ 一模一样

5.​​ hdu1011Starship Troopers​​

加入了代价这个因子,对应的循化条件和状态转移方程改变一下就ok。提供了链式前向星和vector两种建树方式

6. ​​POJ1947Rebuilding Roads​​

跟以前的题都不一样了,这题需要自己推动态规划方程,好好思考,里面有点小知识点,比如num[u]u的子节点数量和求父亲结点fa

 

 

【建树】

注意:这里用的是建树,不要和建图混为一谈,虽然原理一样

两种方法:Vector和链式向前星

vecotr

Vector好处:

单向树:

vector<int>v[N];

val[N];

 

v[u].push_back(v);//u为v的父亲

val[v]=w;       //结点v的权值

 

例题:​​ hdu1011Starship Troopers​​

 

 

缺陷:

1.但是有一些题目不会给标准的给你父节点和子节点,且在后面给你一个价值

比如说这道题:

这时候vector就不起作用了

2.当然在一些这么考stl,或者数据特别大的时候vecto也会失效

 

Vector优点:

1.直接可以得到每一个父节点的子节点数量   v.size()

2.简单易行

链式向前星

原理:点这里

看完原理后,你会发现链式前向星适合存边有权值的问题,所以它适合加入双向边。

这样很完美的解决了有一些题目不会给标准的给你父节点和子节点

链式向前星虽然麻烦一点,但vector更强大。