📌  相关文章
📜  最大化给定根树中节点对之间的差异,使得一个节点是另一个节点的祖先(1)

📅  最后修改于: 2023-12-03 15:10:35.232000             🧑  作者: Mango

最大化给定根树中节点对之间的差异,使得一个节点是另一个节点的祖先

本文将介绍如何在给定根树中找到两个节点之间的最大差异,并且使得其中一个节点是另一个节点的祖先。

问题描述

给定一棵包含 $n$ 个节点的根树,每个节点上有一个整数权值 $w_i$,现在需要从中找到两个节点 $u$ 和 $v$,使得它们之间的差异 $|w_u - w_v|$ 最大,并且要求其中一个节点是另一个节点的祖先。

解法分析

我们可以考虑对树进行遍历,同时维护每个节点子树中权值的最大值和最小值,并计算出该节点向上的最大差异和最小差异。

具体来说,设 $max_i$ 和 $min_i$ 分别表示节点 $i$ 子树中权值的最大值和最小值,$fa_i$ 表示节点 $i$ 的父节点,则有:

  • 对于节点 $i$ 的任意子节点 $j$,有 $max_i \geq max_j$ 和 $min_i \leq min_j$;
  • 对于节点 $i$,其向上的最大差异为 $max_i - w_i$,向上的最小差异为 $w_i - min_i$;
  • 对于节点 $i$ 的任意子节点 $j$,如果 $max_j - w_i > max_i - w_i$,则更新 $max_i = max_j$;
  • 对于节点 $i$ 的任意子节点 $j$,如果 $w_i - min_j > w_i - min_i$,则更新 $min_i = min_j$。

最后,我们可以枚举每个节点 $u$,计算其向上的最大差异和最小差异,然后再找到其子孙节点中权值最大/最小的节点 $v$,计算出差异 $|w_u - w_v|$,并更新答案。

复杂度分析

对于给定根树,我们需要进行一次遍历来计算每个节点的 $max_i$ 和 $min_i$,时间复杂度为 $O(n)$。接着,对每个节点 $u$,需要花费 $O(|u|)$ 的时间来找到其向上的最大差异和最小差异,其中 $|u|$ 表示节点 $u$ 的深度。因此,总时间复杂度为 $O(n^2)$,具体来说,应该是 $O(n \log n)$。

参考代码
def dfs(u, fa):
    global res
    max_up, min_up = float('-inf'), float('inf')
    for v in tree[u]:
        if v != fa:
            dfs(v, u)
            max_up = max(max_up, max_val[v])
            min_up = min(min_up, min_val[v])
    max_val[u] = max(max_up, w[u])
    min_val[u] = min(min_up, w[u])
    res = max(res, max(max_val[u] - w[u], w[u] - min_val[u]))
    for v in tree[u]:
        if v != fa:
            res = max(res, max(max_val[v] - w[u], w[u] - min_val[v]))

n = int(input())
tree = [[] for _ in range(n)]
max_val, min_val, res = [0] * n, [0] * n, 0

for i in range(n):
    w[i] = int(input())
for i in range(n - 1):
    u, v = map(int, input().split())
    tree[u - 1].append(v - 1)
    tree[v - 1].append(u - 1)

dfs(0, -1)
print(res)

以上是该问题的 Python 实现代码。