[DP] CF1060F Shrinking Tree

题意

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

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

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

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

\(1\le n\le 50\)

题解

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

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


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

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

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

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

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

  • \(j \leq i\),缩这条边的时候有 \(\dfrac 12\) 的概率选 \(u\),这必需的。\(j\) 前面的边无论怎么缩都不会影响 \(u\),只需保证后 \(j-1\) 条边不让 \(u\) 变化就行。所以这种情况贡献为 \(\dfrac {f_{v,j-1}}2\)

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

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


posted @ 2022-07-25 16:40  Ilith  阅读(68)  评论(2编辑  收藏  举报