NOIP复健计划——动态规划

本文详细介绍了动态规划在解决树形问题中的应用,包括树形DP的经典题目如POI2011 DYN-Dynamite、JSOI2008魔兽地图、USACO12FEB Nearby Cows G等。通过实例分析,讲解了如何利用动态规划解决树的重建道路、城市环路、最佳团体等问题,以及如何进行优化和综合运用。
摘要由CSDN通过智能技术生成

树形DP

[POI2011] DYN-Dynamite

二分 K K K

check(mid):
能否选出 m m m个点,使得 ∀ i 为关键点, M i n j   i s   s e l e c t e d { d i s ( i , j ) } ≤ m i d \forall i为关键点,Min_{j\ is\ selected}\{dis(i,j)\}\leq mid i为关键点,Minj is selected{ dis(i,j)}mid

进一步转化问题:
一棵树上选 t o t tot tot 个点,使得 ∀ i 为关键点, M i n j   i s   s e l e c t e d { d i s ( i , j ) } ≤ m i d \forall i为关键点,Min_{j\ is\ selected}\{dis(i,j)\}\leq mid i为关键点,Minj is selected{ dis(i,j)}mid,最小化 t o t tot tot。若 t o t ≤ m tot\leq m totm则 check(mid) 为 true,否则 check(mid) 为 false

定义点 i i i被点 j j j覆盖,当且仅当 d i s i , j ≤ m i d dis_{i,j}\leq mid disi,jmid
假设当前考虑到以 x x x为根的子树。
对于在 x x x子树内的关键点,它们要么被 x x x子树内的点覆盖,要么还等着被 x x x子树外的点覆盖。
对于第二种情况,我们需要把问题留到考虑 x x x的祖先时再去解决。

f x f_x fx表示 x x x子树内未被覆盖点到 x x x的最远距离,
g x g_x gx表示 x x x子树内被选择点到 x x x的最近距离。
初值: f x = − ∞ , g x = ∞ f_{x}=-\infty,g_{x}=\infty fx=,gx=
转移: f x = max ⁡ { f y + 1 } f_x=\max \{f_y+1\} fx=max{ fy+1} g x = min ⁡ { f y + 1 } g_x=\min\{f_y+1\} gx=min{ fy+1}
特判:
f x + g x ≤ m i d f_x+g_x\leq mid fx+gxmid,则 x x x子树内所有点都已经被覆盖, f x ← − ∞ f_x\leftarrow -\infin fx
f x = m i d f_x=mid fx=mid,则 x x x一定要选, f x ← − ∞ , g x ← 0 , t o t + + f_x\leftarrow -\infin,g_x\leftarrow 0,tot++ fx,gx0,tot++
g x > m i d   a n d   x 为关键点 g_x>mid\ and\ x为关键点 gx>mid and x为关键点,把问题留给 x x x的父亲解决, f x ← m a x ( f x , 0 ) f_x\leftarrow max(f_x,0) fxmax(fx,0)
Code

重建道路

f [ i ] [ j ] f[i][j] f[i][j]表示以 i i i为根的子树,保留 j j j个点(包括自己),删去的最小边数
初始化: f [ i ] [ 1 ] = s o n [ i ] f[i][1]=son[i] f[i][1]=son[i] s o n [ i ] son[i] son[i]表示 i i i有几个儿子)
转移: f [ u ] [ j ] = m a x { f ( u , j − k ) + f ( v , k ) − 1 } f[u][j]=max\{f(u,j-k)+f(v,k)-1\} f[u][j]=max{ f(u,jk)+f(v,k)1}(−1是因为v和u之间相连的那一条边不删)

注意:我们要获得的子树的根并不一定要是整棵树的根节点
Code

城市环路

基环树
如果这道题是出在树上,那就是最大独立集的裸题
f [ i ] [ 1 / 0 ] f[i][1/0] f[i][1/0]表示选/不选 i i i ,以 i i i为根的子树的最大贡献
f [ u ] [ 1 ] = ∑ v ∈ s o n u f [ v ] [ 0 ] f[u][1]=\sum_{v\in son_u}f[v][0] f[u][1]=vsonuf[v][0]
f [ u ] [ 0 ] = ∑ v ∈ s o n u m a x ( f [ v ] [ 0 ] , f [ v ] [ 1 ] ) f[u][0]=\sum_{v\in son_u}max(f[v][0],f[v][1]) f[u][0]=vsonumax(f[v][0],f[v][1])

考虑在基环树上怎么做:
法一:强制断边
首先把环找出来
对于环上一对相邻点 ( x , y ) (x,y) (x,y),根据题意, x , y x,y x,y不能同时选

  1. 强制 x x x不选,此时 y y y可选可不选,断掉边 ( x , y ) (x,y) (x,y)无影响。断边后做树形dp, f [ x ] [ 0 ] f[x][0] f[x][0]即为此情况下的答案
  2. 强制 y y y不选,此时 x x x可选可不选,断掉边 ( x , y ) (x,y) (x,y)无影响。断边后做树形dp, f [ y ] [ 0 ] f[y][0] f[y][0]即为此情况下的答案
  3. 最终答案= m a x ( f [ x ] [ 0 ] , f [ y ] [ 0 ] ) max(f[x][0],f[y][0]) max(f[x][0],f[y][0])

Code
法二:树形dp+环形dp
博客
Code

[JSOI2008]魔兽地图

这个题的特殊性在于儿子对于父亲节点是有影响的
所以用 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示第 i i i号装备,其中 j j j被祖先用来合成上层装备,花费 k k k元所能获得最大的力量值。

分步转移,第一步先枚举第 i i i 号装备合成多少个,第二步再合并子树贡献。
Code

[JSOI2016]最佳团体

分数规划
二分答案 m i d mid mid,问题转化为:
给定一棵根为0的树。每点点权为 P i − m i d ∗ S i P_i-mid *S_i PimidSi,选定一个点就必须选其所有祖先节点。
问能否取 k k k个节点使得取出点的点权和大于零。

d p [ u ] [ j ] dp[u][j] dp[u][j]表示以 u u u为根的子树,取 j j j个节点所带来的最大收益
合并就是经典树形背包
Code

[USACO12FEB]Nearby Cows G

基础换根dp
f [ i ] [ j ] f[i][j] f[i][j] 表示 i i i 子树内到 i i i 距离为 j j j 的点的权值和
g [ i ] [ j ] g[i][j] g[i][j] 表示 i i i 子树外到 i i i 距离为 j j j 的点的权值和
Code

CF512D Fox And Travelling

首先,在环中的点一定不会被遍历
用类似拓扑排序的过程可以把环上的点全部扔掉,剩下的点会构成若干个有根树和无根树,其中有根树的根是树中唯一与环中的点相连的点

先考虑有根树,设 f i , j f_{i,j} fi,j 表示以 i i i 为根的子树中,选 j j j 个点的方案数
转移: f i , j + k = f p i , j × f s o n , k × ( j + k k ) f_{i,j+k}=fp_{i,j}\times f_{son,k}\times \binom {j+k}{k} fi,j+k=fpi,j×fson,k×(kj+k)
特别地, f i , s i z i = f i , s i z i − 1 f_{i,siz_i}=f_{i,siz_i-1} fi,sizi=fi,sizi1(根节点必须最后删)

对于无根树,感觉可以钦定最后一个被删的是哪个点,但更简单的方法是直接对每个点为根跑一遍有根树的算法,然后发现选 i i i 个点的情况在没被选的 s i z − i siz-i sizi 个点为根的时候会被统计,因此答案要除以 s i z − i siz-i sizi(如果全选是特殊情况,不需要除)

然后就是森林合并答案,就用类似合并子树的方法组合数合并就可以了
Code

CF543D Road Improvement

换根dp
根据套路,
我们设 f u f_u fu为修好 u u u为根的子树中的路的方案数
g u g_u gu为修好整棵树中除了以 u u u为根的子树中的路的方案数

先考虑 f u f_u fu怎么求:
f u , 0 f_{u,0} fu,0表示 u u u子树内无坏边的方案数, f u , 1 f_{u,1} fu,1表示 u u u子树内有坏边的方案数
f u , 0 = ∏ v ∈ s o n u f v , 0 , f u , 1 = ∏ v ∈ s o n u ( f v , 0 × 2 + f v , 1 ) − 1 f_{u,0}=\prod_{v\in son_u} f_{v,0},f_{u,1}=\prod_{v\in son_u} (f_{v,0}\times 2+f_{v,1})-1 fu,0=vsonufv,0,fu,1=vsonu(fv,0×2+fv,1)1
发现 f u , 0 = 1 f_{u,0}=1 fu,0=1,又考虑到 f u = f u , 0 + f u , 1 f_u=f_{u,0}+f_{u,1} fu=fu,0+fu,1
所以 f u = ∏ v ∈ s o n u ( f v + 1 ) f_u=\prod_{v\in son_u}(f_v+1) fu=vsonu(fv+1)

再考虑 g u g_u gu
g u = g f a × f f a f u + 1 + 1 = g f a × ∏ x ∈ s o n f a , x ≠ u ( f x + 1 ) + 1 g_u=\frac{g_{fa}\times f_{fa}}{f_u+1}+1=g_{fa}\times\prod_{x\in son_{fa},x\not=u}(f_x+1)+1 gu=fu+1gfa×ffa+1=gfa×xsonfa,x=u(fx+1)+1
因为逆元不保证存在,所以要记录前缀积和后缀积来避免除法
Code

CF1146F Leaf Partition

博客

CF1016F Road Projects

博客

CF671D Roads in Yusland

博客

CF337D Book of Evil

经典换根dp
f [ u

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值