树形DP<小小结>

来源:互联网 发布:python 服务器监控 编辑:程序博客网 时间:2024/05/19 02:04

什么是树形DP

dcx2001 说,就是树上的DP。状态表示与转移都与树有关,树构成了DP的框架。

怎么实现

一般的树形DP都是逆着 dfs 的过程,用孩子更新父亲。一般都用递归的形式完成。如果知道了 dfs 序,也可以直接逆着 dfs 序来DP。只要能达到目的,想怎么DP就怎么DP啦。

状态一般表示为 f[u][i],其中 u 表示当前计算的节点标号,i 就因题而异了,f[u][i] 表示的不是 u 一个节点的状态,而是 u 的子树的状态。一般都要求出子树的大小,即子树内有几个节点,记作 size[u] 。用到什么就求什么呗。

特殊性质?

树是一个无环连通图,因此 dfs 时不会死循环。树自然分层,DP转移的阶段也就自然有了。就好像分治一样,树形DP的关键在于合并,把 u 的各个孩子 v 的信息合并成自己的。

树形DP十分灵活,它可以和多种算法结合,可以状压,可以背包, 因此做题时思路不能受到限制。

题的类型?

1.点的计数

一般就是简单的求个 size[],在 size[] 上乱搞,可能细节较多。

比如

1.【洛谷2211】最大子树和,题意是给你一个树,每个点都有点权(可以为负),求出最大的连通的一部分使得点权和最大。基本上就是在求 size[] 时变成

size[u]+=max(size[v],0)

时刻更新答案就行了。

2.Garland 给你一棵树,把它分成点权相等的三部分,若不能,输出”No”,否则输出”Yes”,并输出任意一种可行方案。基本思路是先求出所有点权和 all,如果 size[u]=all/3,那么记录 u 作为方案。有一些细节,具体可看题解。

2.用最少的费用覆盖所有的点

给你一个树,每个点都有费用,你选了这个点后,他可以覆盖住到他的路径长度不超过 1(或2) 的点,求出覆盖所有点的最小费用。

比如保安站岗:这道题是覆盖的路径长度不超过1。这种题的一般套路:状态 f[u][0] 表示选 u,f[u][1] 表示不选 u 但选 u 的孩子,f[u][2] 表示不选 u 和孩子但选 u 的父亲。状态转移方程:

f[u][0]=vu(min(f[v][0],f[v][1],f[v][2]))

f[u][1]=vu(min(f[v][0],f[v][1]))f[v][1]f[v][0]f[v][0]使(f[v][0]f[v][1])

f[u][2]=vu(f[v][1])

具体可看这个题解。

3.与叶子节点有关

问题主要与叶子节点有关,这很可以体现树形DP的灵活。

1.背包 有线电视网:一个电视网的电线网络是树形的,总部在根节点,叶子节点是顾客,而其他节点是信号的中转站,每个顾客有一定数的钱,而每一条边都有边权,代表电视网要通这条边所需要的费用,只有顾客的位置与根连通了,他才会把钱给电视网。求电视网在不亏本(即顾客给的钱-通电线所需要的费用≥0)的情况下最多能使多少顾客看上电视。

设 f[u][i] 表示 u 的子树内选 i 个客户时最多挣多少钱。

f[u][i]=maxj=1sizev(f[u][ij]+f[v][j]wu,v)

具体就看看题解吧。

2.状压DP 树有几多愁:给你一个 n(n≤100000) 个点树,让你给树上的每一个点从1到n标点权,一个叶子节点的愁等于叶子节点到根的路径上(包括叶子节点和根)的最小点权,一个树的愁等于树中所有叶子节点的愁的乘积。求这个树的最大愁,保证叶子节点树≤20。

看到20,是否想到状压DP?设 f[s] 表示选了 s 状态的叶子节点时的最大愁,那么

f[s]=maxsi(f[(s)xor(1<<i)]now)

now 是下一个叶子节点的标号,可以用树形DP求出。具体就看题解吧,这道题真的很好,还用到虚数哦!

3.博弈论 树上的博弈:一棵树,叶子节点上有从1开始标的标号,刚开始的时候根部有一个棋子。两个玩家轮流移动棋子,每一步都会将这个棋子向他的某一个孩子移动;如果玩家不能再移动棋子了,那么游戏结束。游戏的结果就是棋子所在叶子上面的数字。游戏的先手想要这个数字最大化,而后手想要这个数字最小化。游戏进行时,两个人知道树的情况。你现在设计叶子节点的标号,若你与先手目的相同,那么游戏的结果是什么?若你后手联合,那么游戏的结果是什么?

此题难想的地方是当不同人移动棋子时,状态表示的含义是不同的。具体可看题解。

4.统计方案数

就是在树上的统计问题。

比如幸运树:一个树,有边权,若边权的十进制表示只有4和7组成,那么这一条边是幸运边。三元组 ( i , j , k ) 表示 i 到 j 和 i 到 k 的路径上都至少有一条幸运边,求 ( i , j , k )的个数。

主要问题是如何分类。令 f[u] 为在 u 的子树内,到 u 的路径中有幸运边的点有几个,令 g[u] 为在 u 的子树外,到 u 的路径中有幸运边的点有几个。那么

ans=u=1n(f[u](f[u]1)+g[u](g[u]1)+f[u]g[u]2)

f[u] 和 g[u] 怎么求,就看题解吧。

5.最大独立集

给定一个树,选出尽量多的点,使任何两个节点均不相邻。

设 f[u][0] 表示在 u 的子树内,不选 u 时最多能选多少点;f[u][1] 选 u 时最多能选多少点。

f[u][0]=vu(max(f[v][0],f[v][1]))

f[u][1]=1+vu(f[v][0])

比如Party at Hail-Bula:基本上就是点的最大独立集裸题,只不过还判断选点最多的方案是否唯一。具体看题解吧,膜拜汝佳大佬哦:)。

6.其它

大模拟 风铃:风铃。。模拟。。大风铃。。大模拟。。。这道题,我,模拟的无言以对。自己看题吧,同样发下我的题解,只是这道题我写的比较墨迹,但思路清晰啊。

还有,还有,像树的重心啊,树的最长路径啊,balabala,我都不写了,写到现在的我感觉身体好像被掏空。那就这样愉快的结束吧。多做些题,就都知道了。:)

原创粉丝点击