📅  最后修改于: 2023-12-03 15:10:46.536000             🧑  作者: Mango
在一棵树中,如果两个节点的距离等于树的高度,则这两个节点被称为理想节点对。现在给定一棵有 n 个节点的树,求该树中所有理想节点对的数量。
该问题可以使用树状数组(Binary Indexed Tree)来解决。
首先,我们可以使用 DFS 遍历树,对于每一个节点,统计距离为树高的节点的数量并将这个值累加到总答案中。
接下来,我们考虑如何求出两个节点之间的距离。假设在 DFS 的遍历中,我们当前处理的节点为 u,它的父节点为 v。如果我们在遍历到 u 的子节点 x 时已经处理好了从 x 到根节点的所有节点的距离,那么我们可以推导出从 u 到根节点的所有节点的距离:
$$dis[u][i] = dis[v][i-1] + 1$$
其中,dis[u][i] 表示从 u 到高度为 i 的节点之间的距离。
因此,我们可以使用树状数组来计算从一个节点到高度为 i 的节点的数量。设 f[u][i] 表示从节点 u 到高度为 i 的节点的数量,则有:
$$f[u][i] = f[v][i-1] + Cnt[dis[v][i-1] + 1] - Cnt[dis[u][i]]$$
其中,Cnt[k] 表示在处理完树的某一部分后,距离根节点为 k 的节点的数量。
最后,我们将所有节点的理想节点对数量累加起来即可。
def dfs(u, pre, h):
global ans
for v in tree[u]:
if v != pre:
dfs(v, u, h + 1)
for i in range(2, h+1):
ans += f[v][i-2] * (Cnt[h+1-i] - Cnt[h-i+1])
Cnt[h] += 1
for i in range(2, h+1):
f[u][i-1] += Cnt[dis[u][i]]
for v in tree[u]:
if v != pre:
for i in range(2, h+1):
f[u][i-1] -= f[v][i-2] * (Cnt[h+1-i] - Cnt[h-i+1])
n = int(input())
tree = [[] for _ in range(n+1)]
for i in range(n-1):
u, v = map(int, input().split())
tree[u].append(v)
tree[v].append(u)
dis = [[0] * (n+1) for _ in range(n+1)]
for i in range(1, n+1):
que = [i]
while que:
u = que.pop(0)
for v in tree[u]:
if dis[i][v]:
continue
dis[i][v] = dis[i][u] + 1
que.append(v)
Cnt = [0] * (n+1)
f = [[0] * (n+1) for _ in range(n+1)]
ans = 0
dfs(1, 0, 1)
print(ans)
时间复杂度:$O(n\log_2{n})$
空间复杂度:$O(n^2)$
使用了树状数组优化,可以满足大部分场景的要求。