如何通过删除子树来最大化树的权重

时间:2019-04-05 14:52:16

标签: binary-tree subtree

有一棵有N个节点(编号1到N)的根树;节点“ 1”是根。每个节点都有一个值;让我们用A(i)表示节点i的值。

以下操作可以执行任意次(包括零次):

1。选择树中仍然存在的任何节点,并删除该节点的整个子树,包括它本身。

2。让我们将利润定义为树中当前存在的所有节点的值的总和减去X⋅k,其中k表示执行此操作的次数。找到最大可能的利润。

我们在这里如何计算“ k”值?(意味着删除时间节点数以获取最佳利润)

示例:-


3(number of nodes,N) ,

5(X)

1 -5 -10 (Values of corresponding nodes)

(edge(s) from 'x'->'y')

1 2

2 3

Output: -4

We remove the sub-tree of node : 2'.

Now,value of our tree is: 1.

Finals answer:- 1-(x)*k,
(k=1); as we have performed the operation of removing the sub-tree only '1' time 
:  1-(5)*1= -4.

注意:并不是说树应该是二叉树,它也可以是普通树。

2 个答案:

答案 0 :(得分:5)

有一个简单的递归算法。您可以在树上执行的最有利的修剪操作是对其所有直接子树执行最有利的修剪操作,或者仅修剪整棵树。可以直接将其翻译为代码。

假设树已被处理成一个数据结构,其中每个节点都有一个表示节点值的value属性和一个存储该节点的子节点列表的children属性,以下Python函数将计算最大利润:

def max_profit(node):
    return max(
        -X,
        node.value + sum(map(max_profit, node.children)))

max调用中有两个选项代表选择是修剪整棵树在根部还是保留根并处理子树。

答案 1 :(得分:3)

该想法是解析树,并查看可以删除哪个子树,以使其利润比其初始状态增加。在删除任何对象之前,请对每个节点进行此分析。然后,删除收益最大的子树。我们可以通过两遍来做到这一点:

1)对树进行深度优先遍历(先离开,然后再缓慢返回根),计算每个节点的利润收益为G(i)=-A(i)+G(j)+G(k)+...,其中i是当前节点,j,k,...是子节点。换句话说,如果我们删除当前节点,那么利润收益就是增加值。

在相同遍历期间,还要计算节点及其子节点的最大利润。这将告诉我们删除节点是否更有利可图,或者删除该节点的子树是否更有利可图。我们将最大利润增长计算为M(i) = max(G(i),M(j),M(k),...),其中i,j,k,...的定义如上。如果不存在子项,只需将其从max等式中删除。

2)进行树的广度优先遍历,如果有iG(i) == M(i),则删除节点G(i) >= X(及其子树)。

def compute_gain(node):
    map(compute_gain, node.children)
    node.gain = -node.value + sum([c.gain for c in node.children])
    node.max_gain = max(node.gain, max([c.max_gain for c in node.children]))

def prune_tree(node):
    if node.gain >= X and node.max_gain == node.gain:
        k += 1
        return False
    node.children = [c for c in node.children if prune_tree(c) == True]