Processing math: 100%

CF1060F Shrinking Tree

前置:CTS2019D2T3


先进行一个转化:初始认为树上没有边,每个节点权值为 1。枚举一个长度为 (n1) 的边集排列,按照这个排列依次加入每条边,加入一条边时将这条边所连接的两个连通块所有点的权值 ×12

可以发现所有边均加入后每个点的权值就是在这个边集排列下成为最后节点的概率。


枚举节点 root 计算它的答案,把 root 拉作整棵树的根。

首先 root 和它的某个儿子之间的边会让 root 权值乘上 12。设该儿子是 v(root,v) 加入时,v 会在某个连通块 S 中。

此时对于边集 {(p,q)|pSqS} 中的所有边,它一定会在 (root,v) 之前加入。

而对于边集 {(p,q)|pSqS},这其中的每一条边一定会在 (root,v) 之后加入,且会对答案产生 12 的贡献;而在 (p,q) 加入的时候,q 节点又可能在某一个连通块内,可以递归进入 q 的子树考虑。

这样考虑有两个好处:第一个是可以找到边之间加入顺序的偏序关系,第二个是就有子问题的性质。


为了描述方便,设对于一个边集排列会让 root 所在连通块变大的边(即会让权值乘上 12 的边)称为主动边,反之称为被动边。加入一条主动边时,可能会导致一些被动边的产生(即上文中所提到的连通块 S 中的边)。

之前的思路是枚举边集排列算主被动边,此时发现主被动边思路优势明显,故考虑枚举主动边和主动边产生的被动边。

考虑一张新图,新图上的点与原树上的边一一对应,如果原树上边 (u,v) 需要在边 (p,q) 之后加入则在新图上从 (u,v)(p,q) 连一条边。故新图上会有这样一些边:

  • 一条主动边向其产生的所有被动边连边;
  • 一条主动边向与其最近的主动边祖先连边(如果存在)。

此时有:新图的所有拓扑序与所有满足当前枚举的主被动边情况的序列的反序一一对应,原因是所有与主动被动边相关的限制全部表现在了图上,而拓扑序正好满足所有偏序关系。


现在变成算拓扑序。注意到新图是树形图,因为对于所有被动边仅有产生它的主动边向它连边,而主动边的导出子图是一棵内向树森林。内向树或者外向树的拓扑序易于计算,但它并不是内向树或外向树。

如果做了前置会很自然地想到进行容斥(麻烦做一下前置我这里就不细写了 QAQ)。对主动边与被动边之间的边容斥,那么新图会变为内向森林,此时只需要考虑每个节点在新图上的 size

被动边 size=1 无需考虑,而主动边 (u,v)uv 原树上的父亲)在新图上的 size 可以发现等于 v 在原树上的子树大小减去原树 v 的子树中选择不与主动边连边的被动边数量。那么每条主动边就只关心儿子里面被动边的选择情况了。

DP:设 fi,j 表示原树 i 节点子树内有 j 条被动边选择不与主动边连边,i 节点内部的所有主动边和被动边的贡献总和。

先考虑对于某一个状态 fu,p 如何转移到父亲上,设原树上 u 节点子树大小为 sizeu

  • (i,u) 是主动边,那么乘上计算拓扑序的贡献 1sizeup 和选点概率 12 并转移到 fi,p
  • (i,u) 是被动边且选择不与主动边连边,那么乘上容斥系数 1 并转移到 fi,p+1
  • (i,u) 是被动边且选择与主动边连边,那么乘上容斥系数 1 并转移到 fi,p

对于多个子树的合并显然是树形背包。答案是 (u,root)esizeu1i=0fu,i2(sizeui),原因是 root 的所有儿子必须要是主动边。

然后就做完了。单次的 DP 复杂度是 O(n2) 的,故总复杂度为 O(n3)


吐槽:容斥主动边和被动边之间的边要开 long double,容斥主动边和主动边之间的边开 double 就过了???

Code

posted @   cjoier_Itst  阅读(662)  评论(4编辑  收藏  举报
编辑推荐:
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· SQL Server 内存占用高分析
· .NET Core GC计划阶段(plan_phase)底层原理浅谈
阅读排行:
· 盘点!HelloGitHub 年度热门开源项目
· 某Websocket反爬逆向分析+请求加解密+还原html
· 02现代计算机视觉入门之:什么是视频
· 回顾我的软件开发经历:我与代码生成器的涅槃之路
· DeepSeek V3 两周使用总结
历史上的今天:
2019-04-07 HNOI2019
点击右上角即可分享
微信分享提示