1 条题解
-
0
题意理解
我们有一棵 个结点的有根树 (根是 号结点)。 定义 的生成规则为:
已知。
是在 的每个叶结点下面连接一棵 的根结点(即把 复制一份,根接到 的每个叶子上)。
要求 的直径(路径上的结点数)。
1. 基本思路
树的直径常用两次 BFS/DFS 求法:
从任意点出发找到最远的点 ;
从 出发找到最远的点 , 到 的路径就是直径。
但这里 可能很大(), 的结点数会指数级增长,不能显式建树。
我们需要找到 直径的递推规律。
2. 符号与定义
设:
表示树 的直径(结点数)。
表示从根到叶子的最长路径的结点数(根深度为 )。
表示从根到叶子的最长路径的结点数(其实 就是这个)。
表示从根出发的最长路径的结点数(其实和 一样)。
表示树中离根最远的结点到根的距离(结点数减 是边数,这里我们统一用结点数)。
但更关键的是: 设 = 从根出发的最长路径长度(结点数), 设 = 树中任意两点之间的最长路径(即直径)。
那么 就是 的根到最远叶子的结点数, 就是 的直径。
3. 递推分析
3.1 从 到 的构造:在 的每个叶子下接一个 的根。
那么:
的叶子有 个。
每个叶子下面挂一个 ,所以每个叶子所在的“位置”会多出 的路径(从该叶子到新子树中最远的叶子)。
3.2 新直径的可能情况
的直径可能出现在:
完全在某个 内部:。
完全在某个新加的 内(不可能比情况 1 大,因为 当 时?不一定,要小心)。
经过 的一部分和某个新加的 的一部分: 路径形如:在 中从结点 到某个叶子 ,然后进入该叶子下面的 到达其最深的叶子 。 这条路径长度 = 。
为了最大化这个,我们应取 中离 最远的点 。 对于固定的 (它是 的一个叶子),离它最远的点可能是另一个叶子 ,那么路径就是 的直径,但这样 和 都是叶子,它们之间的路径不经过新加的子树,所以不进入 ,这其实是情况 1。
我们要进入新子树,必须让路径的一端在新子树中。 所以考虑: 路径一端在某个新加的 的最深叶子 ,另一端在另一个新加的 的最深叶子 (或 中的某个点)。
3.3 更清晰的分解
设:
= 的直径长度。
= 中从根到叶子的最大结点数(即高度,根为 1 层)。
= 中从根到叶子的最大结点数(高度)。
的直径可能为:
(完全在 内部)。
路径从 中某个点 ,走到某个叶子 ,然后进入该叶子的 到达其最深叶子:长度 = 。 对固定的 ,最大化 就是找 中离 最远的点,这个最大值是 吗?不一定,因为 是叶子,离它最远的点可能是另一个叶子,距离就是 ,但这样 也是叶子,路径完全在 中,不加 。 所以我们要让 在另一个新子树中:即路径穿过 连接两个不同的新子树。
3.4 跨两个新子树的路径
考虑 中两个不同的叶子 和 ,它们下面各挂了一个 。 路径:从 下面的 的最深叶子 ,到 下面的 的最深叶子 。 长度 = 。
那么 最大是多少? 和 是叶子,它们的距离等于 $depth[u] + depth[v] - 2\times depth[\mathrm{lca}(u,v)]$。 为了最大化它,我们取 中深度最大的两个叶子,且它们的 LCA 是根(即在不同分支上)。 实际上, 中两个叶子的最大距离就是 吗? 不一定,因为 的直径端点不一定是叶子? 不,树的直径端点一定是叶子(除非只有一个结点)。所以是的,直径端点就是两个叶子。
所以 。
因此这种情况的长度 = ? 不对,检查: 到 : 条边? 我们用的是结点数。 到 在 中的结点数 = (因为 是 的根的父亲? 等等,构造是: 的叶子 下面接 的根 ,所以 到 有一条边, 到最深叶子 有 条边,所以 到 有 个结点? 不对, 到 :路径 ,结点依次是 ,总数为 ? 我们算一下:
的高度(结点数)是 ,即从根到最深叶子有 个结点。 现在 的根 接在 下面,所以 到 的结点数 = (u) + (从 到 ) = ? 不对,这样重复计算了 和 吗? 我们明确一点:
内部:根 到最深叶子 有 个结点。 现在 是 的叶子, 与 连边,所以 到 的路径:,结点数 = ? 不对,因为 到 是 个结点,其中 是第一个, 是最后一个。所以 到 的结点数 = (u) + (r到A) = 。
同理 到 也是 个结点。
那么 到 的路径:$A\to \dots \to r_u \to u \to \dots \to v \to r_v \to \dots \to B$。 结点数 = $(h_1) + [u \to v \text{ 在 } T^{m-1} \text{ 中的结点数}] + (h_1)$。 但 在 中的结点数 = (边数+1)。 所以总结点数 = = 。
取 (因为 是直径端点,它们之间的距离是 条边? 等等,之前混淆了: 是直径的结点数,边数 = 。 那么 的结点数 = (因为路径上的结点数就是 )。 所以 到 结点数 = 。
3.5 另一种情况
可能直径是一个端点在 内部(非叶子),另一个端点在新子树的最深叶子。 长度 = (因为从 的根到最深叶子 ,再接新子树的最深叶子 ,但这样会重复计算叶子? 要小心)。
实际上,从 的根到新子树最深叶子的结点数 = ? 我们来算: 路径:根 -> ... -> 叶子L (H个结点) -> T^1的根 -> ... -> 最深叶子 (h_1个结点),但叶子L和T^1的根是不同结点,所以总结点数 = H + h_1。
所以这种情况长度 = 。
3.6 递推公式
设 = 的直径(结点数), = 中从根到最深叶子的结点数。
初始: = 的直径, = 的高度(结点数)。
递推:
情况 A:直径完全在 内部:。
情况 B:直径跨两个新子树:? 不对,上面我们得到 ? 检查: 我们取 的直径端点 (叶子),它们下面接 ,则新路径长 = ? 不对,上面算的是 ? 再检查: 到 结点数 = (A到u) + (u到v) + (v到B) = 。 但 到 是 个结点? 不对, 到 结点数 = (见前推导),所以总 = (因为u和v重复计算了一次)? 我们画图:
路径: (新子树1最深) -> ... -> (T^1根) -> (T^{m-1}叶) -> ... -> (T^{m-1}叶) -> (T^1根) -> ... -> (新子树2最深)。
结点数 = (A到u) + (u到v) + (v到B) - 1? 因为u和v算了两次? 我们按结点序列数:
A到u: A, ..., r_u, u 共 个结点。 u到v: u, ..., v 共 个结点(因为u,v是直径端点)。 v到B: v, r_v, ..., B 共 个结点。
拼接:A...u...v...B,u和v各出现一次,所以总 = $(h_1+1) + (d_{m-1} - 2) + (h_1+1) = 2 h_1 + d_{m-1}$。
好,所以情况 B 长度 = 。
情况 C:直径从 的根到新子树最深叶子:长度 = 。
所以:
$$d_m = \max(d_{m-1},\ 2h_1 + d_{m-1},\ H_{m-1} + h_1) $$显然 ,所以 。
3.7 的递推
的根到最深叶子的路径: = 的根到最深叶子( 个结点) + 该叶子下接的 的根到最深叶子( 个结点) - 1(重复计算该叶子)? 不对,应该是 ? 检查:
路径:根(T^{m-1}) -> ... -> 叶子L (H_{m-1}个结点) -> 根(T^1) -> ... -> 最深叶子(h_1个结点)。 叶子L和根(T^1)是不同结点,所以总 = 。
所以 。
初始 ( 的高度)。
因此 。
3.8 最终递推
已知(输入树的直径), 已知(输入树的高度,根深度1)。
递推:
其中 。
所以:
初始 已知。
3.9 解递推
递推式:
已知。
如果 ,观察: (因为 )。 $d_3 = \max(2 h_1 + d_2,\ 3 h_1) = \max(2 h_1 + 2 h_1 + d_1,\ 3 h_1) = \max(4 h_1 + d_1,\ 3 h_1)$。 因为 ,,所以 。
模式:? 检查 m=2: 对。 m=3: 对。
所以通解:
,如果 $$d_1 \geq h_1$
如果 ,则可能后来被 超过。 但 是输入树的直径, 是输入树的高度,一般 ? 不一定,比如链:高度=h,直径=h,所以 。 那么 总是成立? 因为直径至少等于高度(根到最深叶子)。 所以 。
因此最终:
4. 算法步骤
读入 和父数组。
建树 。
求 的直径 (结点数)。
求 的高度 (从根到最深叶子的结点数,根深度1)。
输出 。
时间复杂度 。
5. 最终公式
其中 是 的直径(结点数), 是 的高度(结点数,根深度为1)。
- 1
信息
- ID
- 3949
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者