info: { blogIcon: 'https://cdn.luogu.com.cn/upload/usericon/765493.png', blogUser: 'OIerBoy', blogAvatar: 'https://cdn.luogu.com.cn/upload/usericon/765493.png', blogStartDate: '2023-04-22', webpageTitleOnblur: '(o?v?)ノ Hi', webpageTitleOnblurTimeOut: 1000, webpageTitleFocus: '(*′?`*) 欢迎回来!', webpageTitleFocusTimeOut: 1000, webpageIcon: "https://cdn.jsdelivr.net/gh/BNDong/Cnblogs-Theme-SimpleMemory@master/img/webp/blog_logo.webp", { enable: true, // 是否开启日/夜间模式切换按钮 auto: { // 自动切换相关配置 enable: false, // 开启自动切换 dayHour: 5, // 日间模式开始时间,整数型,24小时制 nightHour: 19 // 夜间模式开始时间,整数型,24小时制 } } },

P1272 重建道路

2023-09-08

题目

P1272 重建道路

难度&重要性(1~10):6.5

题目来源

luogu

题目算法

树形 dp,背包

解题思路

一道把树形和背包结合的很好的题。
第一眼看到这道题我们就可以大致的写一个状态,\(f_{i,j}\) 表示在以 \(i\) 为根的子树内,保留 \(j\) 个节点的子树的最小破坏数目。
那么,我们考虑如何才能比较好的转移。
首先,记 \(s_v\) 表示在 \(i\) 的子节点 \(v\) 中选取 \(s_v\) 个节点来更新 \(i\)。我们再定义一个 \(c_v\) 表示当选取 \(s_v\) 个节点最少需要删除的边数。
这样一个非常粗糙的转移方程就写好了:

\[f_{i,j}=\min{\sum\limits_{\exists (i,v),v\neq fa}c_v(\sum s_v=j)} \]

那么我们如何详细的写出这个转移方程呢?
我们需要再仔细观察一下:在 \(v\) 中选取 \(s_v\) 个节点来更新 \(i\),使 \(\sum s_v=j\),同时 \((\sum c_v)_{min}\)。
有意思的地方来了,这句话有没有感觉在哪里见过,对背包啊。
那么我们就需要简单的完善一下我们的状态方便理解,\(f_{i,j,k}\) 表示在以 \(i\) 为根的子树内,在只考虑前 \(j\) 个子节点时,保留 \(k\) 个节点的子树的最小破坏数目。
那么我们就可以得到转移方程:

\[f_{i,j,k}=\min(f_{i,j-1,k}+1,f_{i,j,k-s_v}+f_{v,siz_v,s_v}) \]

注意,这里的 \(f_{i,j-1,k}\) 是要 \(+1\) 的,因为从 \(j-1\) 转移到 \(j\) 时我们需要将子树 \(v\) 也删掉。
到这里,这道题基本上就已经可以了,但是它的可以优化的。
仔细观察转移方程可以发现式子中其实和 \(j\) 的关系不大,那么我们就可以将 \(j\) 这一维压掉。
新的 \(f_{i,j}\) 表示的其实是和我们最初的状态意义是一样的,只不过我们现在可以得到一个清晰的转移式:

\[f_{i,j}=\min(f_{i,j}+1,f_{i,j-s_v}+f_{v,s_v}) \]

注意,这里我们由于把原本的 \(j\) 给压掉了,所以我们就需要先保证 \(f_{i,s_v}\) 比 \(f_{i,j}\) 先更新到,就需要倒序枚举。
而需要简单考虑的是 \(f\) 的初始化,由于刚开始时我们还没有考虑任何一个子节点,我们就只需要将 \(f_{i,0}=0\) 就可以了。
最后考虑统计答案,由于并不是根节点 \(1\) 的答案就是最优的,因为它是考虑了它的所有子节点的,所以我们需要判断的是每一个点的答案是否最优。同时,如果当前查看的不是根节点,我们还要进行 \(+1\) 操作,因为它还要删除它与它父亲的边。
答案就是:\(ans=\min\left(\min\limits_{i=2}^n\{f_{i,P}\}+1,f_{1,P}\right)\)。

完状态

已完成

posted @ 2023-09-08 20:28  OIerBoy  阅读(36)  评论(0)    收藏  举报