ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

学习笔记——树形DP

2021-08-05 16:03:11  阅读:210  来源: 互联网

标签:DP 笔记 circ 树形 dp 节点 本题


前言

学完树形$DP$,$NOIP$会考的所有$DP$我们就都学完了,所以让我们一鼓作气,开始树形$DP$的学习之旅吧!

一、树形$DP$的基本概念

顾名思义,树形$DP$就是在树这种数据结构上进行$DP$(这不是废话吗?),通过有限次遍历树,记录相关信息,以求解问题。因为树形$DP$是建立在树上的,而树中的父子关系本身就是一个递归结构(满足子问题重叠性),所以自然而然地就衍生出了两种$DP$顺序:

1.叶子节点 $\Rightarrow $ 根节点:就是将叶子节点的信息向上传到父亲节点,在父亲节点处进行信息的整合。最后由根节点记录的信息得到最优解。

例如本题可以将下属来不来得到的权值作为信息传递到上级(题解)(我的代码)

2.根节点 $\Rightarrow $ 叶子节点:取所有点作为一次根节点进行求值,此时父节点得到整棵树的信息,只需要去除这个儿子节点$DP$值的影响,然后再转移给这个儿子。(此做法一般不用,但有时可能有奇效)

树形$DP$的顺序:一般按照${\color{Red}\colorbox{White}{后续遍历}}$的顺序(先处理儿子节点再处理当前节点(这样才符合$DP$的三个基本条件))

实现方式:树形$DP$一般用${\color{Red}\colorbox{White}{记忆化搜索}}$实现(既然是记搜当然用的是递归了)(类似于树剖的第一个dfs)

时间复杂度:一般的树形$DP$的时间复杂度是$O(N)$(因为每一个节点只会被遍历一次),如果有附加维$M$,则复杂度为$O(N\times M)$。

二、树形$DP$的几种类型

1.背包类树形$DP$

既然我们前面将背包和树形$DP$联系在一起学了,那我们就先从我们熟悉的背包类入手吧!(这样能增加我们的信心,减少我们对树形$DP$的畏惧心理)

1.先来一道入门题(树上01背包)(题解)(我的代码)

通过本题,我们就可以大致了解树形$DP$的思路--从根节点出发不断向子树进行搜索,再将子树的信息合并到该节点上。(注意:本题要考虑只选该节点与子树连接的这一条边的情况)

2.经典的树上01背包(题解)(我的代码)

本题我们又学会了一种思想--建虚点。因为本题是在森林中选一定的节点(选完父节点才可以选子节点),但我们又不可以只由一棵树得到最优解,所以我们可以考虑建一个虚点($0$),令它向所有树的根节点连一条边,接着只要对以虚点为根节点的子树进行树形$DP$求出最优解即可。

3.细节较多的树上01背包(题解)(我的代码)

通过本题,我们要学会在树形$DP$时注意细节--该节点与它儿子节点相连的边到底可不可取,以后做树形$DP$题推导状态转移方程时要仔细考虑这个问题,才能更正确的做出树形$DP$题。

4.状态转移方程含义比较新奇的题(内层循环顺序讲解清楚的题解)(我的代码)

本题告诉我们:

(1)树形$DP$的状态转移方程记录的可以不只是一个最优解,还可以记录该状态对最终答案的贡献

(2)我们可以通过建立双向边的方式将一棵树强行转化为以1号节点为根节点的树,然后通过遍历顺序重新确立父子节点

(3)我们要注意该状态有没有被更新过,可以通过思考将一些不可能更新答案的状态排除(本题中还是初始值-1的状态),加快程序的运行效率。

5.(上一道搜索题(大雾)(讲的很详细的题解)(我的代码)

先吐槽一下:普及$DP+IOI$输入$=$提高难度

好了好了,来总结一下本题的收获

(1)联想已学:遇到另类的输入时,可以联想一下我们已学算法中有没有类似的结构。例如本题可以用类似线段树的建树方式来解决输入问题。

(2)根据题意合理运用填表法和刷表法

还是先简单解释一下这两个词吧!

填表法 :就是一般的动态规划,当前点的状态,可以直接用状态方程,根据之前点的状态推导出来。

刷表法:由当前点的状态,更新其他点的状态。

刷表法需要注意:只用于每个状态所依赖的状态对它的影响相互独立

这么说大家是不是还是一头雾水,举个例子:如果状态$A$对状态$B$有影响,状态$C$也对状态$B$有影响,当状态$A$的影响和状态$C$的影响相互不影响,就可以运用刷表法。

本题中就记录到达该走廊末尾需要花费的时间(设为$tim$),令$j$表示分配给左儿子的时间,$k$表示分配给右儿子的时间,然后更新以$u$为根节点的树花$tim+j+k$秒可以取得的最大价值。这样可以极大地减少思考难度。

继续挖坑 (挖坑太多后面会不会填不完啊)

1.P3354 [IOI2005]Riv 河流

2.P4322 [JSOI2016]最佳团体

3.P4037 [JSOI2008]魔兽地图

4.P4516 [JSOI2018]潜入行动

2.普通树形$DP$

经历过树形背包的洗礼,我们应该了解到了树形$DP$的基本思路,接下来就开始真正的树形$DP$吧!

1.最大权独立集问题(题解)(我的代码)

本题作为树形$DP$的经典例题,当然会在各种场合出现。本题要求父子节点二选一,使总价值最大,自然是一道典型的最大权独立集问题板子。做这类题,我们可以在$DP$数组上多开一维,这一维只有$0$或$1$组成,表示该节点选或者不选,然后在根节点处统计答案最大值即可。

2.最小权覆盖集问题(覆盖边)(题解)(我的代码)

本题要求 在给定的树上取最小的节点数,使所有边都至少有一个端点在选中的集合中。 我们还可以仿照第一问的思路继续解题-- 在$DP$数组上多开一维,表示该节点选或者不选,然后在根节点处统计答案最小权值 。所以,只要我们深刻理解树形$DP$的方法,就可以如法炮制做其他题。

3.最小权覆盖集带点权的问题(覆盖点)(题解)(我的代码)

本题看上去像例题2的加强版,但其实本题要求守点,而不是像例题2一样守边。就是这一个看似细小的差距,却导致了代码的千差万别。例如下面这张图:

如果我们只守1、4号点,那这一条链上的点就都可以守到,但2<->3这一条边明显没有守到。所以本题中我们要考虑三种情况:

1.$x$节点被自己覆盖,即选择$x$点来覆盖$x$点

2.$x$节点被儿子$y$覆盖,即选择$y$点来覆盖$x$点

3.$x$节点被父亲$fa$覆盖,即选择$fa$点来覆盖$x$点

然后分类讨论进行状态转移,最后在根节点处取$min(f[1][0],f[1][1])$作为代价的最小值。(因为根节点没有父亲节点,所以不用讨论该情况)

CF1120D Power Tree(题解)(我的代码)

本题想到$DP$的思路并不难,但主要恶心在输出每个点是否可能成为最优解,这就导致一道本来黄$\sim$绿的树形$DP$题强行升紫。

思路:

我们用dp[u][0]表示以$u$为根节点的子树将所有叶子节点控制的最小代价,用
dp[u][1]表示以$u$为根节点的子树中还剩一个叶子节点未控制的最小代价。

  • $dp[u][1] = \sum\limits dp[v][0] - max(dp[v][0] - dp[v][1])$(我们可以贪心选择一颗子树,使$dp[u][1]$的代价最小)

  • $dp[u][0] = min(sum[u],dp[u][1] + val[u])$(显然,我们可以不选当前节点取尽$u$的所有子树,也可以选当前节点)

我们再建一堆辅助数组,用于输出答案,用g[u]表示$u$的儿子节点中dp[v][0]-dp[v][1]的最大值,用
num[u]表示dp[u][0]可以有多少个dp[v][1]转移而来,用sum[u]表示所有dp[v][0]之和,再用can[u][1]表示可以通过dp[u][1]转移到其父亲节点can[u][0]表示可以通过dp[u][0]转移到其父亲节点。

  • 如果$can[u][0]=1$

  • $\circ$转移到$can[v][0]$

  • $\circ$ $\circ$ 如果$num[u]>1$,则$can[v][0]=1$,因为$v$节点不一定传递到$dp[u][1]$

  • $\circ$ $\circ$ 如果$g[u]!=dp[v][0]-dp[v][1]$,即$v$节点一定传递到$dp[u][0]$,$can[v][0]=1$。

  • $\circ$ $\circ$ 如果$dp[u][0]==sum[u]$,即$v$节点一定传递到$dp[u][0]$,$can[v][0]=1$。

  • $\circ$转移到$can[v][1]$

  • $\circ$ $\circ$ 如果$sum[u]-dp[v][0]+dp[v][1]+val[u]==dp[u][0]$,即贪心选择的子树是$v$节点,显然$can[v][1]=1$。

  • 如果$can[u][1]=1$

  • $\circ$转移到$can[v][0]$

  • $\circ$ $\circ$ 如果$num[u]>1$,则$can[v][0]=1$,因为$v$节点不一定传递到$dp[u][1]$

  • $\circ$ $\circ$ 如果$g[u]!=dp[v][0]-dp[v][1]$,即$v$节点一定传递到$dp[u][0]$,$can[v][0]=1$。

  • $\circ$转移到$can[v][1]$

  • $\circ$ $\circ$ 如果$g[u]==dp[v][0]-dp[v][1]$,即贪心选择的子树是$v$节点,显然$can[v][1]=1$。

又到了扔题时间

1.P4084 [USACO17DEC]Barn Painting G

2.P3174 [HAOI2009]毛毛虫

3.P3621 [APIO2007]风铃

4.P3574 [POI2014]FAR-FarmCraft

5.P3523 [POI2011]DYN-Dynamite

6.P4099 [HEOI2013]SAO

7.P3237 [HNOI2014]米特运输

3.换根树形$DP$

1.基本思路

  • 先以$1$号节点,进行一遍$dfs$,令$f[u]$表示以$u$为根节点的子树的最优解。

  • 将根节点转移到其儿子节点上,并不断更新$f[to]$(假设$to$为$u$的儿子节点)

  • 将第二步推而广之,逐渐更新完整颗树

由上面的操作可以看出,换根$DP$其实就是不断利用以$1$为根节点得到的信息更新以其他点为根节点得到的信息。

1.来一道入门题--找使所有结点的深度之和最大的根节点(题解)(我的代码)

作为入门题,当然是要让我们熟悉换根$DP$基本思路的题。本题可以令$f[i]$表示以$i$号节点为根节点的树的深度和,用根节点从$u$移动到$to$($u$的儿子节点)时以$to$为根节点这颗子树的所有节点的深度$-1$,而其他节点的深度$+1$进行状态转移。

2.找使所有节点到当前点最短距离的点(题解)(我的代码)

一样的板子和套路,不过因为极大值比较大,所以先以$f[1]$为极大值再更新其他值即可。(白白WA40pts)

3.求距离每个节点不超过k的点的权值和(题解)(我的代码)

4.找使该节点所有子树大小和最大的点(题解)(我的代码)

5.询问该节点经过改造后是否能成为重心(题解)(我的代码)

本题思路比较好想(改造该点子树中最大节点数不超过$\frac{n}{2}$的子树),但是码代码时一定要养成好习惯,不要打出int to=e[i].nxt这样的细节错误 (关键这种错误找了一个下午+一个晚上才找出来)

因为要去考$NOIP$,所以还是挖坑 (估计也不会填了,毕竟考完还要补文化)

我回来填坑了$!$

1.P6419 [COCI2014-2015#1] Kamp(题解)(我的代码)

2.P3647 [APIO2014]连珠线(题解)(我的代码)

标签:DP,笔记,circ,树形,dp,节点,本题
来源: https://www.cnblogs.com/wujianxiang/p/15103725.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有