统计子树中城市之间最大距离
难度:
标签:
题目描述
给你 n
个城市,编号为从 1
到 n
。同时给你一个大小为 n-1
的数组 edges
,其中 edges[i] = [ui, vi]
表示城市 ui
和 vi
之间有一条双向边。题目保证任意城市之间只有唯一的一条路径。换句话说,所有城市形成了一棵 树 。
一棵 子树 是城市的一个子集,且子集中任意城市之间可以通过子集中的其他城市和边到达。两个子树被认为不一样的条件是至少有一个城市在其中一棵子树中存在,但在另一棵子树中不存在。
对于 d
从 1
到 n-1
,请你找到城市间 最大距离 恰好为 d
的所有子树数目。
请你返回一个大小为 n-1
的数组,其中第 d
个元素(下标从 1 开始)是城市间 最大距离 恰好等于 d
的子树数目。
请注意,两个城市间距离定义为它们之间需要经过的边的数目。
示例 1:
输入:n = 4, edges = [[1,2],[2,3],[2,4]] 输出:[3,4,0] 解释: 子树 {1,2}, {2,3} 和 {2,4} 最大距离都是 1 。 子树 {1,2,3}, {1,2,4}, {2,3,4} 和 {1,2,3,4} 最大距离都为 2 。 不存在城市间最大距离为 3 的子树。
示例 2:
输入:n = 2, edges = [[1,2]] 输出:[1]
示例 3:
输入:n = 3, edges = [[1,2],[2,3]] 输出:[2,1]
提示:
2 <= n <= 15
edges.length == n-1
edges[i].length == 2
1 <= ui, vi <= n
- 题目保证
(ui, vi)
所表示的边互不相同。
代码结果
运行时间: 36 ms, 内存: 16.1 MB
解释
方法:
该题解采用状态压缩和二维 DP 的思路来解决问题。首先,通过 DFS 预处理计算出任意两点之间的距离,存储在二维数组 dis 中。然后,枚举任意两个点 i 和 j,通过 DFS 计算以 i 和 j 为直径端点的子树数量。在 DFS 过程中,对于每个点 x,如果满足一定条件(与 i 和 j 的距离关系),就可以选择 x,每棵子树之间互相独立,因此子树数量的计算可以采用乘法原理。最后,将不同直径对应的子树数量累加到答案数组 ans 中。
时间复杂度:
O(n^3)
空间复杂度:
O(n^2)
代码细节讲解
🦆
在DFS预处理阶段,如何确保已计算出所有城市对之间的准确距离?是否有可能存在未被正确更新的距离值?
▷🦆
dfs2函数中使用的条件`(di[y] < d or di[y] == d and y > j)`和`(dj[y] < d or dj[y] == d and y > i)`具体是如何筛选子树中的节点的?这些条件是否足够确保找到所有正确的子树?
▷🦆
题解中提到,如果`di[x] + dj[x] > d`则`cnt += 1`,这里的逻辑是什么?为什么在这种情况下需要增加计数?
▷