📌  相关文章
📜  查找给定树中理想节点对的数量(1)

📅  最后修改于: 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)$

使用了树状数组优化,可以满足大部分场景的要求。