[DP] CF1060F Shrinking Tree
题意
对于一棵有 个节点的树 。当 的节点数多于一个时,反复执行以下操作:
-
等概率地选取 中的一条边。
-
收缩选取的边:即合并这条边连接的两个点 和 。得到的新点的编号等概率地从 和 中选取一个。
当这个过程结束时, 只剩一个节点了,它的编号可能是 中的任意一个数。对于每个编号,请输出最终得到这个编号的概率。
。
题解
好神奇啊...感觉只能停留在理解层面,现场做哪怕缺少一环就肯定无法想出了...
感谢 zxy 大佬的教诲,我现在理解这个题了。
范围较小,那么枚举树上特殊点,而后将其作为根往往是很大程度上简化问题的有效手段。
对于此题来讲,枚举点 作为最后保留下来的点则不用关心其他编号,而将 设为根导出了一个树形 DP 的初步思路: 表示仅考虑 子树内的边,以任意顺序缩掉但最后留下的编号是 的概率。
这个转移有一个很明确的思路:对于 的儿子 ,如果我某一时刻缩掉了 的边并且保留的是 ,则可以看做是将 的儿子都挂在了 下面。此时,缩掉 子树所有点且根编号不变的一个缩边排列,唯一对应着将这些挂上 的儿子全缩掉且 编号不变的序列,而缩掉每个子树的边对于「 编号不变」是独立的——子问题的形式初具雏形。
但一个问题是 的子树缩到某个时候的形态,是不太能记录进状态的,我们需要找到更简洁的方式来刻画,但我想了很久都不会。有一个关键的 observation 是: 这条边之前的合并边一定无用,我们不考虑,也不应该考虑这些边。这说明我们还需要记录时间,也就是缩边序列的填充状态,才可以找到子问题。
对缩边序列进行填充。为保有子问题的形式,状态设置为: 表示对于 的子树的缩边序列已经填充了后 位,前面的随便填的所有方案,已填充的位不会影响到 的概率之和。从儿子 转移到 时,枚举最关键的一条边 的出现时间 :
-
,缩这条边的时候有 的概率选 ,这必需的。 前面的边无论怎么缩都不会影响 ,只需保证后 条边不让 变化就行。所以这种情况贡献为 。
-
,既然我不关心 前面的边有没有影响,那自然我枚举这条边没卵用, 子树该咋整咋整,贡献为 。
那么最后需要一个背包来合并这些子树的缩边序列,转移时注意乘上组合数的系数就可以了(注意已填充与未填充的边,这两个组合数系数要分别算)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端