[DP] CF1060F Shrinking Tree

题意

对于一棵有 n 个节点的树 T 。当 T 的节点数多于一个时,反复执行以下操作:

  • 等概率地选取 T 中的一条边。

  • 收缩选取的边:即合并这条边连接的两个点 uv 。得到的新点的编号等概率地从 uv 中选取一个。

当这个过程结束时, T 只剩一个节点了,它的编号可能是 1,,n 中的任意一个数。对于每个编号,请输出最终得到这个编号的概率。

1n50

题解

好神奇啊...感觉只能停留在理解层面,现场做哪怕缺少一环就肯定无法想出了...

感谢 zxy 大佬的教诲,我现在理解这个题了。


n 范围较小,那么枚举树上特殊点,而后将其作为根往往是很大程度上简化问题的有效手段。

对于此题来讲,枚举点 x 作为最后保留下来的点则不用关心其他编号,而将 x 设为根导出了一个树形 DP 的初步思路:fu 表示仅考虑 u 子树内的边,以任意顺序缩掉但最后留下的编号是 u 的概率。

这个转移有一个很明确的思路:对于 u 的儿子 v,如果我某一时刻缩掉了 (u,v) 的边并且保留的是 u,则可以看做是将 v 的儿子都挂在了 u 下面。此时,缩掉 v 子树所有点且根编号不变的一个缩边排列,唯一对应着将这些挂上 u 的儿子全缩掉且 u 编号不变的序列,而缩掉每个子树的边对于「u 编号不变」是独立的——子问题的形式初具雏形。

但一个问题是 v 的子树缩到某个时候的形态,是不太能记录进状态的,我们需要找到更简洁的方式来刻画,但我想了很久都不会。有一个关键的 observation 是:(u,v) 这条边之前的合并边一定无用,我们不考虑,也不应该考虑这些边。这说明我们还需要记录时间,也就是缩边序列的填充状态,才可以找到子问题。

对缩边序列进行填充。为保有子问题的形式,状态设置为:fu,i 表示对于 u 的子树的缩边序列已经填充了后 i 位,前面的随便填的所有方案,已填充的位不会影响到 u 的概率之和。从儿子 v 转移到 fu,i 时,枚举最关键的一条边 (u,v) 的出现时间 j

  • ji,缩这条边的时候有 12 的概率选 u,这必需的。j 前面的边无论怎么缩都不会影响 u,只需保证后 j1 条边不让 u 变化就行。所以这种情况贡献为 fv,j12

  • j>i,既然我不关心 i 前面的边有没有影响,那自然我枚举这条边没卵用,v 子树该咋整咋整,贡献为 fv,i

那么最后需要一个背包来合并这些子树的缩边序列,转移时注意乘上组合数的系数就可以了(注意已填充与未填充的边,这两个组合数系数要分别算)。


posted @   Ilith  阅读(70)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示