题解:CF804D Expected diameter of a tree
集训习题。特别地,让我们膜拜一下教练 zmwang。
题目要求在给定森林上回答多次随机连边后直径期望的询问。若把询问点分别所在的两棵树记为 \(V\) 与 \(U\),随机等概率选取 \(a\in V\)、\(b\in U\) 后加上一条边 \(a-b\)。若两点本来同属一棵树,则不会形成树结构,答案固定 \(-1\)。否则加边后得到一棵新树,其直径满足
\(D_{\text{new}}=\max\bigl(D_V,D_U,1+e_a+e_b\bigr)\),
这里 \(D_V,D_U\) 是两棵原树的直径,\(e_x\) 表示顶点 \(x\) 的偏心距(到两端点的距离最大值)。
对单棵树先做两遍广搜,任选一点做第一次 BFS 得到最远端点 \(p\),以 \(p\) 再来一次 BFS 得到另一端点 \(q\) 和直径 \(D\),接着把第三次 BFS 换成简单地在第二遍得到的最短路树上回溯就能算出所有顶点到 \(p,q\) 的距离。于是偏心距 \(e_x=\max(\text{dist}(x,p),\text{dist}(x,q))\) 可以 \(O(n)\) 求完。把这些 \(e_x\) 排序后连同前缀和保存在全局数组,顺带记录节点数 \(s\) 与直径 \(D\)。
一次询问若涉及两棵不同的树,只需计算
设 \(D_{\max}=\max(D_V,D_U)\)。为了快速累加,把较小的那棵树记为 \(A\),较大的记为 \(B\)。遍历 \(A\) 中每个 \(e_a\) 时,在 \(B\) 的有序偏心距数组里二分出最后一个满足 \(e_b\le D_{\max}-1-e_a\) 的位置,其之前的 \(\ell\) 个点与 \(e_a\) 搭配时 \(\max\) 恰好取 \(D_{\max}\),贡献 \(\ell\cdot D_{\max}\)。后面的部分利用前缀和一次性求出 \(\sum(1+e_a+e_b)\)。这轮复杂度 \(O(|A|\log|B|)\)。
因为不同树对总共不会超过 \(\sqrt n\) 级别,所有未缓存的树对最多触发同阶复杂度的真正计算,随后将结果以键 \(\text{key}=id_1\cdot N+id_2\) 存进哈希表,再遇到同一对树即可 \(O(1)\) 取值,整体复杂度摊成 \(O(n\sqrt n+q\log n)\)。

浙公网安备 33010602011771号