树形 DP 做题记录
树形DP
树形 DP 是一种常见的 DP 形式,具有代表性的有树上背包、换根 DP,基环树上 DP。
一些和路径相关的问题的常见状态是把当前路径已确定的端点数计入状态。
还有一些小技巧。比如树上背包如果必须选择根节点,可以直接在 dfs 序上进行转移。
CF1146F Leaf Partition
题意:有一棵树,定义\(S\)为一个叶子集合,\(f(S)\)为这个集合的最小联通子图,求有多少把叶子分成若干集合的方案使得任意集合对于\(S,T\),\(f(S)\cap f(T)=\varnothing\)。
思路:树形dp。发现对于一个点,如果子树只传上来一条链,那么必须和其他链合并,否则就可以不和其他的合并,于是设\(f[x][0/1/2]\)表示点\(x\)的子树上传\(0/1/\geqslant 2\)条链的方案数。转移有
于是就做完了。
CF1394D Boboniu and Jianghu
题意:有一棵 \(n\) 个点的树(\(1\le n\le 2\times10^5\)),第 \(i\) 个点有参数 \(a_i,b_i\)。(\(1\le a_i,b_i\le10^6\))
现在要求把这棵树剖分成若干条链(链包括端点),使每条边恰好出现在一条链中,且要求链上的点的 \(b_i\) 单调不降或单调不增。一条链的权值定义为链上所有点的 \(a_i\) 之和。
求在所有剖分方案中,链的总权值最小为多少。
思路:一眼树形DP,直接维护\(dp[i][0/1]\)表示上升、下降的情况。
其实正解也差不多,重点当\(h[x]=h[y]\)时是类似反悔贪心的思路来确定有多少是上升的,有多少是下降的。
CF1499F Diameter Cuts
题意:给定一棵 \(n\) 个节点的树和一个正整数 \(k\)。求有多少种边的集合,使得在将此集合中的所有边断开后,形成的所有连通块的直径都不大于 \(k\)。
思路:直接DP就可以。设\(f[x][i]\)表示\(x\)向下的最长链长度是\(i\)的方案数,于是转移有\(f[x][i]\leftarrow f[x][i]\times\sum\limits_{j\leqslant k}f[y][j]\)(割掉这条边)和\(f[x][max(i,j+1)]\leftarrow f[x][i]\times\sum\limits_{i+j+1\leqslant k}f[y][j]\),然后优化一下枚举量就可以了。
[AGC010C] Cleaning
题意:一棵树,第\(i\)个节点上有\(a_i\)个石头,每次选择两个叶子节点(度数为1的节点),将路径上经过的(包括起点终点)所有节点上都取走一个石头,如果路径上有一个点上没石头这个操作就不能进行,问能不能取完所有石头。
思路:看到路径加就往树上差分上想,果不其然想不出来。
直接考虑求出每个点会向上传多少条路径,那么有\(f[x]=2a_x-\sum\limits_{y\in son[x]}f[y]\)。再考虑什么条件才有解。首先有\(f[x]\in[0,a_x]\)和\(f[root]=0\),以及\(\max\limits_{y\in son[x]}f[y]\leqslant a_x\)。
以后遇到一道题不要一直往一个方面想。
CF1442E Black, White and Grey Tree
题意:给一棵树,每个点是灰色(0),白色(1)或者黑色(2)。你每次可以选择一个连通块,然后在这个连通块里面选择一些点,把它们和它们所连的边删去。你不能同时选择黑点和白点。求删完整棵树的最小操作次数。
思路:小清新题。
自己大概想法是树形DP随便搞搞,不过多半是假的。
正解:先考虑只有黑白的情况,那么把同色连通块缩点后,每次的策略就是不断删同色的叶子,因此答案就是直径长度除以二上取整。有一个简单的处理方法是如果两点同色,那么边权为0,否则为1,直接求直径即可。
再考虑有灰色点的情况。这时就相当于是可以把灰色点染成白或黑点,要求最小化直径长度,可以直接DP,设\(dp[i][0/1]\)表示\(i\)点染成黑/白是子树的最大深度,\(g[i][0/1]\)表示经过\(i\)的直径长度最小值,于是有\(f[x][i]=\max(f[x][i],f[y][j]+(j\ne i))\),\(g[x][i]=\max(g[x][i],\min(f[x][i]+f[y][j]+(i\ne j)))\),最终有\(ans=\max\limits_i(g[i][0],g[i][1])\)。
P3647 [APIO2014] 连珠线
题意:给定一棵树,从里面选出若干个“三连点”的边,使边权和最大。
思路:终于来写连珠线了。
发现蓝线连接的只会是 \(son[x]\rightarrow x\rightarrow fa[x]\),于是考虑设 \(f[x][0/1]\) 表示 \(x\) 是否是蓝线中点时子树中的最优情况,那么转移就是
然后就是换根了,不过有不少细节。
P4202 [NOI2008] 奥运物流
思路:神秘基环树 DP 题。
先考虑怎么算 \(R(i)\)。
由于形成的一定是一棵基环内向树,于是假定环长为 \(n\),那么可以列出方程组 \(R(i)=C_i+kR_{i\pmod n+1}\),解得 \(R(1)=\dfrac{\sum(C_ik_{i-1})}{1-k^n}\);再假定环长为 1,那么有 \(R(1)=\sum C_ik^{dep[i]}\)。
综上,我们得到了 \(R(1)=\dfrac{\sum C_ik^{dis(i)}}{1-k^{len}}\),len 表示环长。
因此每次修改一定是把父节点改成 \(n\) 更优。考虑树形 DP,设 \(f[x][i][d]\) 表示 \(x\) 子树内 \(x\) 的深度为 \(d\) 还有 \(i\) 次修改的最大可靠值。每次类似背包合并即可。如果要对环进行修改,就要枚举环长,因此复杂度是 \(O(n^5)\)。
P4297 [NOI2006] 网络收费
思路:好题。
对于两个点,如果异色,那么一定会做 \(f\) 的贡献,如果同色,那么当且仅当不是 LCA 子树里出现次数最多的颜色时,有 \(2f\) 的贡献。
对于路由器,如果和子树里颜色相同的叶子有 \(cnt\) 个,那么贡献就是 \(\frac{cnt}{2}f\),于是路由器的颜色一定是子树内出现次数更多的颜色,而且每个叶子的贡献也只和祖先节点的颜色有关。
因为树是完全二叉树的形态,于是可以考虑把祖先的颜色压进状态里,如同 [JLOI2015] 战争调度一样,每次递归两次,然后设计状态 \(f[i][j]\) 表示 \(i\) 的子树里有 \(j\) 个 1 的最小代价,背包合并即可。
P4516 [JSOI2018] 潜入行动
题意:给定一棵树,如果在一个节点 \(u\) 放一个监听设备,那么与 \(u\) 相邻的节点 \(v\) 都能被监听,但是 \(u\) 不会被监听。现在有 \(m\) 个监听设备,问能够监听整棵树且恰好使用了 \(m\) 个监听设备的方案数。
思路:很厉害的优化代码长度的方法。
容易想到就是树上背包,状态是 \(f[x][i][0/1][0/1]\) 表示点 \(x\) 的子树里选 \(i\) 个,\(x\) 有没有放装置,\(x\) 是否被覆盖。
然后就可以根据 \(0/1\) 的取值分 4 种情况讨论。
正经人谁写大分讨啊。
首先,\(x\) 是否放装置是和 \(y\) 无关的,因此这一维不变,然后剩下的情况中如果 \(x\) 没被覆盖且 \(y\) 未放装置就不合法,否则都合法,而且后一维是 \(x\) 被覆盖和 \(y\) 放了装置或起来,于是就好写多了。
P6534 [COCI2015-2016#1] UZASTOPNI
题意:题意是说给定一棵有根树,需要从中选出一些节点符合:每个选中节点的父亲也被选中,任意选中节点在原树对应的子树内所有选中的节点点权连续。选中的所有节点不能有权值相同的。求方案数,其中两个方案不同当且仅当它们选出的点的点权集合不同。
思路:可以给 \(n,v\) 各加一个 0。
对于一个点 \(x\),假设选了的孩子之一是 \(y\),那么 \(y\) 选择的等差数列不会跨过 \(v_x\),于是一定是都大于 \(v_x\) 或者都小于 \(v_x\),于是对于一个点只需维护比 \(v_x\) 大的能选到多少和比 \(v_x\) 小的能选到多少,而且可以用 bitset 优化,复杂度为 \(O(\dfrac{nv}{w})\)。
P9454 [ZSHOI-R1] 巡城
题意:有一张图,保证如果有环那么所有环的交是 1 号点,求从 1 号点开始 dfs,每次随机一个点为出边,每个点的 dfs 序的期望。
思路:好题。
首先考虑树的情况,那么兄弟之间两两贡献的系数是 \(\dfrac{1}{2}\),每个点的贡献就是父亲的答案加上 \(1+\dfrac{siz(fa(x))-siz(x)-1}{2}\)。考虑不同树的贡献,需要用换根维护,发现此时不能直接用 \(\dfrac{1}{2}\),两棵树的贡献是 \(\dfrac{cnt_T}{cnt_S+cnt_T}\),其中 \(cnt_x\) 是 \(x\) 这棵树与 1 相连的点的数量,于是可以把所有 \(cnt\) 一样的树统一处理,因为本质不同的出现次数是 \(O(\sqrt{n})\) 量级的,于是复杂度是 \(O(n)\)。
Fox And Travelling
题意:给定一张 \(n\) 个点 \(m\) 条边的无向图。一个点只有当与它直接相连的点中最多只有一个点未被选择过时才可被选择。询问对于每个 \(k \in [0,n]\),有序选择 \(k\) 个点的方案数。
思路:首先,如果图没有什么性质是不好做的,但是可以发现在环上的点一定没发被遍历到,因此可以用类似拓扑排序的方法排除这些点,于是就只会剩下若干有根树、无根树。
对于有根树,直接树上背包即可。
对于无根树,需要以每个点为根算一遍,可以发现每一种包含 \(i\) 个点的方案会被算 \(siz-i\) 次,除掉即可。
最后把所有树的答案用背包合并即可。
CF613D Kingdom and its Cities
题意:给定一棵树,每个询问给出一些关键点,要求删掉最少的点使这些点两两不联通,无解输出-1。
思路:先判无解:只要有一个关键点的父亲也是关键点就无解。因为会被删除的点肯定是这些点中一些点的\(lca\),所以考虑建虚树,然后树形DP。具体来讲,设\(g_x\)表示当前有没有关键点与\(x\)直接联通(若\(x\)为关键点则\(g_x=1\)),\(f_x\)表示点\(x\)的答案。转移时先\(f_x=\sum\limits_{y\in son(x)}f_y\),然后根据\(x\)是否是关键点与\(\sum\limits_{y\in son(x)}g_y\)的值(设为\(sum\))分类讨论:
1.\(g_x=0\):
如果\(sum>1\)那就将点\(x\)删去,\(f_x++\);
如果\(sum=1\)那就将\(g_x=1\)
如果\(sum=0\)自然不变
2.\(g_x=1\)那与\(x\)联通的点都得删,\(f_x+=sum\)
最后\(f_1\)就是答案,复杂度\(\sum n\times\log(\sum n)\)。
P4383 [八省联考 2018] 林克卡特树
题意:在树上选出 \(k+1\) 条不相交的链使得链的边权和最大。
思路:WQS二分+树形DP。看到恰好多少条就想到了WQS二分,二分选出一条链的代价,然后用树形DP算出选出多少条链最优。具体的,设 \(dp[i][0/1/2][0/1]\) 表示在$ i$ 的子树中,点 \(i\) 的度数为0/1/2,最后的0/1表示是权值还是选了几条链。转移时:
复杂度:\(O(n\log(n))\)。
P8352 [SDOI/SXOI2022] 小 N 的独立集(其实这题本来也不是这个题单里的)
题意:给定大小为\(n\)的树,每个点点权可以为\([1,k]\),求最大权独立集大小为\(i\in[1,nk]\)的方案数。
思路:一开始以为是普通的树形dp,后来才发现是dp套dp。首先考虑如果是直接求最大权独立集大小,那么就是设\(f[x][0/1]\)表示\(x\)点选/不选的最大值,然后\(f[x][0]=\sum\limits_{y\in son(x)}\max(f[y][0],f[y][1])\),\(f[x][1]=val[x]+\sum\limits_{y\in son(x)}f[y][0]\),而在计数时,我们考虑将\(f[x][0]\)和\(f[y][0]\)记入状态,设\(g[x][v0][v1]\)表示\(x\)子树中\(f[x][0],f[y][0]\)分别为\(v0,v1\)的方案数,这就是一个树上背包问题,只不过复杂度较高。我们发现这个状态本身就是\(O(n^3k^2)\)的,需要优化,于是我们改变定义,设\(f[x][1/0]\)表示是否强制不选点\(x\)的答案,我们发现\(f[x]\)有一些性质,比如\(0\leqslant f[x][0]-f[x][1]\leqslant val[x]\leqslant k\),那么我们就可以简化状态,记\(g[x][v][d]\)表示在\(x\)的子树中,\(f[x][0]\)为\(v+d\),\(f[x][1]\)为\(v\)的方案数,每次转移时有\(g'[x][i+p+q][\max(i+j+p,i+p+q)-(i+p+q)]+g[x][i][j]\times g[y][p][q]\rightarrow g'[x][i+p+q][\max(i+j+p,i+p+q)-(i+p+q)]\),这样一来复杂度就是\(O(n^2k^4)\)的了。
P2515 [HAOI2010] 软件安装
思路:先缩点,然后会形成一棵树,然后考虑怎么树上背包。
有一种很神奇的 DP 方法。
设 \(dp[i][j]\) 表示考虑 dfs 序的前 \(i\) 项,重量为 \(j\) 的最大权值,那么转移有 \(dp[i][j]+v[dfn[i]]\rightarrow dp[i+1][j+s[dfn[i]]]\) 和 \(dp[i][j]\rightarrow dp[i+siz[i]][j]\)。
Tree Elimination
给定一棵\(n\)个点的树,点编号\(1 \sim n\),第\(i\)条边连接\(a_i\)和\(b_i\)。
初始时你有一个空的序列,树上的\(n\)个点都有标记。
现在按照边的编号从小到大考虑每一条边:
-
如果这一条边连接的两个点都有标记,则选择其中的一个点,擦除它的标记并将它的编号放入序列的末端;
-
否则什么都不做。
求能够由上述操作得到的不同的序列数量。
思路:考虑树形 DP。
对于一条边 \((u,v)\),我们要确定的是删除 \(u\) 上的标记还是 \(v\) 上的标记还是不删,同时钦定我们的选择是合法的,这样就可以确定最终的序列,那么对最终序列的计数就是对操作方案的计数。
设 \(f[x][0/1/2/3]\) 表示 \(x\) 是被自己父亲边之前的边操作、被父亲边操作、被父亲边之前的边操作、没有被操作。
对于 \(f[x][0/2]\),转移时枚举覆盖 \(x\) 的儿子 \(y\),首先点 \(y\) 不能被操作,即 \(f[y][2/3]\),那么对于在 \(y\) 前被考虑的点 \(z\),一定会被覆盖,贡献就是 \(f[z][0/1]\),否则就不能被 \((x,z)\) 覆盖,贡献是 \(f[z][0/2/3]\),合起来就是 \(\sum\limits_{y\in son[x]}(\prod\limits_{z<y}f[z][0/1]\times f[y][2/3]\times \prod\limits_{z>y}f[z][0/2/3])\),可以维护前后缀积来转移。
对于 \(f[x][1]\),是上一种情况的简化版,贡献为 \(\prod\limits_{y<fa[x]}f[y][0/1]\times\prod\limits_{y>fa[x]}f[y][0/2/3]\)。
对于 \(f[x][3]\),所有的儿子都要被操作,就是 \(\prod f[y][0/1]\)。
Nested Rubber Bands
题意:给定一棵 \(n\) 个点的树,第 \(i\) 条边连接 \(u_i\) 和 \(v_i\)。
你需要将每一个节点画成一个二维平面上闭合几何图形,当且仅当 \(u\) 和 \(v\) 之间有边相连,这两个点对应的几何图形边界相交(注意包含不算边界相交)。
我们定义一个序列 \(a_1,a_2,\ldots,a_k\) 是好的,当且仅当对于任意的 \(2\le i\le k\),\(a_{i-1}\) 所对应的几何图形完全包含 \(a_i\) 所对应的几何图形。
求好的序列最长可以是多少。
思路:首先有性质:对于一个点 \(x\),不可能存在 3 个子树 \(a,b,c\),使得这 3 个子树中,除了 \(a,b,c\) 还有点在序列中。
证明:假设还有 \(u,v,w\) 这 3 个点在序列中,因为 \(a,c\) 与 \(v\) 没有边相连,所以一定在 \(v\) 的两边,但 \(x\) 要与 \(a,c\) 相交但不和 \(v\) 相交,显然不可行。
于是这个序列一定满足存在一条链使得所有点到链的距离不超过 1,即一条链和直接相邻的点的最大独立集。
设 \(f[x][0/1]\) 表示在 \(x\) 的子树中,\(x\) 在链的一段,在不在序列中的最大答案,转移类似求树的直径。
P1600 [NOIP2016 提高组] 天天爱跑步
题意:给一棵树和若干条路径,每个点有权值 \(a_i\),求有多少条路径的第 \(a_i+1\) 个点是 \(i\)。
思路:首先,一条路径不好直接处理,可以拆成两段,这样我们就只用考虑从上到下和从下到上的两种路径。
这时就可以类似树上差分,用桶来维护两类路径的答案,在 dfs 时实时维护即可。
[省选联考 2023] 城市建造
题意:给定一张 \(n\) 个点 \(m\) 条边的无向连通图 \(G = (V, E)\),询问有多少该图的子图 \(G' = (V', E')\),满足 \(E' \ne \varnothing\) 且 \(G - E'\) 中恰好有 \(|V'|\) 个连通块,且任意两个连通块大小之差不超过 \(k\),保证 \(0 \le k \le 1\),请输出答案对 \(998,244,353\) 取模的结果。
思路:首先有一些性质。如果两个点被选择,那么如果有一条简单路径连接这两个点,这条路上的所有点都要被选择。由此可以推出,如果一个点双里面选了两个点,那么整个点双都要被选择。因此,建出圆方树,钦定选一个方点表示选择了整个点双,那么我们最终选出的一定是方点的连通块,且删掉这些方点后每个连通块的大小之差不大于 \(k\)。
接着可以想到枚举连通块大小 \(d\) 来计数,而可以证明合法的 d 是 \(\left\lfloor\frac{n}{i}\right\rfloor\) 或 \(\left\lfloor\frac{n}{i}\right\rfloor-1\),因此只有 \(n\sqrt n\)种。
然后我们考虑如何计数。
设 \(f_i\) 表示:如果 \(i\) 是圆点,删掉它的父亲方点的方案数;如果是方点,删掉它自己的方案数。
当 \(k=0\) 时,可以证明答案一定是 0/1,因此对于一个点 \(x\) 的儿子 \(y\),有:如果 \(x\) 时方点,\(f_x=\prod f_y\);如果 \(x\) 是圆点,只有 \(siz_y<d\) 的 \(siz_y\) 之和为 \(d-1\),且所有 \(siz>=d\) 的 \(f_y\) 都为 1 时,\(f_x=1\),否则为 0。
当 \(k=1\) 时,多的情况是如果没有 \(siz_y<d\) 的点,那么每一个 \(siz_y=d\) 的 \(y\) 都可以和 \(x\) 在同意连通块内,会多产生一种情况,直接加上即可。
[省选联考 2023] 填数游戏
题意:Alice 和 Bob 是一对好朋友。今天,他们约好一起玩游戏。一开始,他们各自有一张空白的纸条。接下来,他们会在纸条上依次写 \(n\) 个 \([1,m]\) 范围内的正整数。等 Alice 写完,Bob 在看到 Alice 写的纸条之后开始写他的纸条。
Alice 需要保证她写下的第 \(i\) 个数在集合 \(S_{i}\) 中,Bob 需要保证他写下的第 \(i\) 个数在集合 \(T_{i}\) 中。题目保证 \(1 \leq\left|S_{i}\right|,\left|T_{i}\right| \leq 2\) 。
Alice 喜欢相同,因此,她希望她写下的数与 Bob 写下的数对应位置相同的个数尽量多。Bob 喜欢不同,因此,他希望他写下的 \(n\) 个数 \(b_{1}, \ldots, b_{n}\) 互不相同。在此基础上,Bob 希望他写下的数与 Alice 写下的数对应位置相同的个数尽量少。
即设 Alice 写下的数为 \(a_{1}, \ldots, a_{n}\),Bob 写下的数为 \(b_{1}, \ldots, b_{n}\),记 \(X\) 为满足 \(1 \leq i \leq n, a_{i}=b_{i}\) 的下标 \(i\) 的个数,则
- Alice 希望最大化 \(X,\)
- Bob 在保证 \(b_{1}, \ldots, b_{n}\) 互不相同的前提下希望最小化 \(X\)。
你首先想知道 Bob 能否保证他写下的 \(n\) 个数互不相同。如果 Bob 能够做到,你想知道在双方均采取最优策略的前提下 \(X\) 的值会是多少。
思路:题意转化为:每个 \(T_{i,0}\) 与 \(T_{i,1}\) 之间连边,根据 \(|S_i\cap T_i|\) 的大小每条边有定向的代价和能否定某种方向,每个点最多被一条边指定,Alice要选择一种方案使得Bob的所有合法定向方案中代价最小值最大。
因为每个点最多被一条边指定,所以有 \(|V|\geqslant|E|\),因此每个连通块只能是基环树或者树。
先考虑基环树,对于不在环上的边,只能是叶向的,而且环上的边的方向必须一致,所以只有两种情况,很容易计算。
再考虑树的情况,Bob的选择一定是形如钦定一个点为根,所有边都是相对这个点叶向的,这样一共有 \(|V|\) 种方案。考虑从一个点到儿子时子树外的最小值-1,子树内加1,可以使用换根DP实现。
总复杂度 \(O(n+m)\)。
[八省联考 2018] 林克卡特树
题意:在树上选出 \(k+1\) 条不相交的链使得链的边权和最大。
思路:WQS二分+树形DP。看到恰好多少条就想到了WQS二分,二分选出一条链的代价,然后用树形DP算出选出多少条链最优。具体的,设 \(dp[i][0/1/2][0/1]\) 表示在 \(i\) 的子树中,点 \(i\) 的度数为0/1/2,最后的0/1表示是权值还是选了几条链。转移时:
复杂度:\(O(n\log(n))\)。
P4649 [IOI2007] training 训练路径
题意:给定一个无向图,你需要删掉一些边,使得此图没有长度为偶数的简单环。删掉第 \(i\) 条边有 \(C_i\) 的花费,有些边又是不能删的。不能删的边形成图的一棵生成树。保证每个点的度数不超过 10。
思路:没看出最终是个仙人掌,输麻了。
首先,把会形成偶环的非树边删掉,这时只剩一些奇环,我们发现,如果有一条边同时出现在两个奇环里,那么就会形成一个偶环,因此每条边至多出现在一个环里,即这张图是个仙人掌。
于是就可以 DP。先变成求可以留下的非树边权值的最大值。我们设 \(f[i][S]\) 表示点 \(i\) 不考虑 \(S\) 中的儿子的答案,那么对于一条 \(lca(u,v)=i\) 的非树边,如果不选,那么不选时有 \(f[i][S]=\sum\limits_{son\notin S}f[son][0]\),选的时候贡献有两部分,一是 \(f[u][0]+f[v][0]\),二是对于路径上其他点 \(p\),设 \(p\) 不包含 \(u\) 或 \(v\) 的儿子集合为 \(K\),贡献为 \(\sum f[p][K]\),于是有 \(f[i][S]=\max(f[i][S|x|y]+val)\)。
[ARC121F] Logical Operations on Tree
题意:给定一棵树,给每个点填 \(0\) 或 \(1\),给每条边填 \(\text{AND}\) 或 \(\text{OR}\),在所有 \(2^{n+n-1}\) 种填法中,计数有多少种满足存在一种缩边的顺序,使得每次把一条边的两个端点缩成一个点,权为原端点与边的运算值,最终点的权为 \(1\)。
思路:考场上什么都想到了,就是 DP 有一步没想通。
首先,策略肯定是先把 AND 的边缩起来,因此合法的条件就是有一个 1 点周围都是 OR 边或者一个 AND 边连通块内都是 1 点。发现这个条件还是比较复杂,考虑补集,就是每个 AND 连通块内至少有一个 0 点。于是就可以 DP。对于一条边,如果当做 OR 边就相当于是把连通块割开。
设 \(dp[i][0/1]\) 表示当前考虑到点 \(i\),当前连通块是否合法的方案数,那么有转移两种:
-
\(dp[i][0]\leftarrow 2dp[i][0]\times dp[j][0]+dp[i][1]\times dp[j][0]+dp[i][0]\times dp[j][1]\)
-
\(dp[i][1]\leftarrow dp[i][1]\times dp[j][1]\)。
P4895 独钓寒江雪
题意:给定一棵无根树,求其中本质不同的独立集的个数。
思路:好题。
因为是无根树,而且和同构有关,不难想到以重心为根转成有根树。
考虑和正常的求独立集的 DP 不同在哪里,就是如果有同构的子树那么方案数会有重复,于是可以把同构的子树一起处理,可以用组合数计算。
对于两个重心的情况,新建一个节点当做根即可。
P1864 [NOI2009] 二叉查找树
题意:给你一棵treap,你可以通过改变树的形态使得树上所有节点子树访问次数和的和最小,改变形态有代价。
思路:根据二叉查找树的性质,这棵树的中序遍历就是所有点从小到大排序后的结果,而这是无法更改的,可以从这个方面入手。
题目中说可以让点权修改为任意实数,这就意味着可以有相同权值。把权值离散化一下就可以开始 DP 了。
设 \(f[l][r][k]\) 表示当前考虑中序遍历在 \([l,r]\) 中的点,整个子树的权值都 \(\ge k\) 的最小访问代价+修改代价。转移时枚举作为根的点 \(x\),如果 \(k\le val[x]\),有 \(f[l][r][k]\leftarrow f[l][x-1][val[x]]+f[x+1][r][val[x]]+\sum hz_i\),其中 \(hz_i\) 表示 \(i\) 的访问频度,这是不改变 \(x\) 的权值的情况;改变 \(x\) 的权值的情况就是 \(f[l][r][k]\leftarrow f[l][x-1][k]+f[x+1][r][k]+K+\sum hz_i\)。复杂度 \(O(n^4)\)。
P8290 [省选联考 2022] 填树
题意:给一棵树,每个点的点权要么是 0,要么是 \([l_x,r_x]\) 中的数,你要选择一条链,让这条链上的点权不为 0,求所有可能的满足非 0 极差不超过 \(k\) 的方案数和权值和。
思路:首先考虑朴素的暴力。我们枚举所有点权所在的区间 \([l,l+k]\),然后计算答案,因为要取到下界,就要容斥掉 \([l+1,l+k]\) 的答案。求答案的过程可以用树形 DP,每个点能选的是一个区间,那么可以算出当前点为链头和为 LCA 的答案,于是就可以做到 \(O(nV)\)。
考虑优化。我们发现对于选择的区间 \([l,l+k]\),每个点能取的范围是一个一次函数,那么总的贡献就是由这些一次函数形成的次数为 \(n\) 的多项式,这就不难想到用拉格朗日插值,代入 \(n+2\) 个点值就可以求出答案。对于求权值和,每个点能选的权值和是一个二次函数,那么总共就是 \(2n+1\) 次多项式,也可以同样处理。
复杂度 \(O(n^3)\)。
[AGC007E] Shik and Travel
题意:一颗 \(n\) 个节点的二叉树,每个节点要么有两个儿子要么没有儿子。边有边权。你从 \(1\) 号节点出发,走到一个叶子节点。然后每一天,你可以从当前点走到另一个叶子。最后回到 \(1\) 号节点,要求到过所有叶子并且每条边经过恰好两次。每天的路费是你走过的路径上的边权和,你的公司会为你报销大部分路费,除了你旅行中所用路费最高的,行走路线是从叶子到叶子的那一天的路费。求你自己最少要付多少路费?
思路:可能算是二分+DP优化(?)。
首先,显然可以二分答案。接着就是判定是否合法。设\(dp[x][a][b]\)表示在\(x\)的子树中,第一步走的距离是\(a\),最后一步是\(b\)是否可行,转移时枚举\(i,j\)表示左右儿子之间的连边在子树中的部分,那么有\(dp[x][a][b]=f[ls][a-w[ls]][i]\&f[rs][j][b-w[rs]](i+j+w[ls]+w[rs]\leqslant mid)\)
这样DP很暴力考虑怎么优化。我们发现,如果有两个合法状态\(f[x][a][b],f[x][c][d](a\leqslant c,b\leqslant d)\),那么\(f[x][c][d]\)显然是没用的,于是可以把这样的无用状态去掉,即按\(a\)排序后,\(b\)必须是递减的。在合并的时候,我们可以用双指针求出\(ls,rs\)中的每一对对应的状态,因此每次会增加\(2\min(L,R)\),其中\(L,R\)表示左右子树中的状态数,因此最后的总状态数是\(O(n\log n)\)的。