树的直径
假设我们枚举直径端点 ,考虑求出一个极大的以 为直径的子树 ,那么除了端点外剩下的点取和
不取都无所谓,这个直径对答案的贡献为直径的长度乘以 。
那么如何得到这个极大的子树,考虑我们求直径的过程,随便选定一个点,求最远点,然后以这个最远点为
起点求最远点即得到直径,那么极大的子树必然不会包含 或
的点。而剩下的点不会影响我们求直径的过程,也就是说,如果我们保证任意极大
子树中的点 满足 ,那么不妨取 开始 DFS 求直径,
可以得到 是一条直径。
这样处理会存在两个问题,一个是如果一个子树有多个长度相同的直径就会重复计算,另一个是 显
然无法接受。
重复计算的问题比较好解决,例如可以限制对于 的情况,我们仅仅在 的情
况下统计,或者说 字典序小于 时统计。
而这个求解过程可以使用 bitset 优化,按 从大到小枚举 (如果相同则按字典序排序以防止
重复计算),我们可以在枚举的同时用 bitset 维护距离小于等于直径的点集,那么每次可以取的点数就是
和 对应 bitset 的交的点集的大小,处理完当前直径就在彼此的 bitset 中删除对方,于是可以在
时间内完成本题。