Как максимизировать вес дерева, удалив поддеревья

Существует корневое дерево с N узлами (пронумерованными от 1 до N); узел «1» является корнем. Каждый узел имеет значение; обозначим значение узла i через A(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.

ПРИМЕЧАНИЕ: дерево не должно быть бинарным, это может быть и обычное дерево.


person sdrtg ghytui    schedule 05.04.2019    source источник
comment
В вашем примере возможно ли, что Output:- -4 должен быть Output:- -14? Кроме того, избегайте использования :-, дефис делает его очень запутанным со знаком минус.   -  person Gilles-Philippe Paillé    schedule 05.04.2019
comment
Вы пометили это бинарное дерево, но ничего в описании проблемы не говорит, что это бинарное дерево.   -  person user2357112 supports Monica    schedule 06.04.2019


Ответы (2)


Для этого существует простой рекурсивный алгоритм. Наиболее выгодная обрезка, которую вы можете выполнить для дерева, — это либо выполнить наиболее выгодную обрезку для всех его прямых поддеревьев, либо просто удалить все дерево. Это можно перевести непосредственно в код.

Предполагая, что дерево было преобразовано в структуру данных, где каждый узел имеет атрибут value, представляющий значение узла, и атрибут children, хранящий список дочерних узлов узла, следующая функция Python вычислит максимальную прибыль:

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

с двумя параметрами в вызове max, представляющими выбор: либо удалить все дерево в корне, либо сохранить корень и обработать поддеревья.

person user2357112 supports Monica    schedule 06.04.2019
comment
Можете ли вы написать код более подробно, чтобы я мог понять? - person sdrtg ghytui; 06.04.2019
comment
@ user2357112 Я согласен, что ваше решение намного проще, без необходимости обрезать дерево, чтобы узнать максимальную прибыль. - person Gilles-Philippe Paillé; 06.04.2019
comment
@ Жиль-Филипп Пайе Я новичок в деревьях, можете ли вы объяснить мне его решение? Спасибо :-) - person sdrtg ghytui; 06.04.2019
comment
каково основное условие нашей функции? Что делать, если у узла больше нет потомков, что он будет делать? - person sdrtg ghytui; 07.04.2019
comment
@Firexsecred: затем map перебирает 0 дочерних элементов и делает 0 рекурсивных вызовов, а sum суммирует 0 чисел и дает 0. - person user2357112 supports Monica; 07.04.2019
comment
@user2357112 user2357112 проблема в том, что я dk python, поэтому запутался в значении карты, какова будет временная сложность этого алгоритма, скажем, для «n» узлов? Спасибо:-) - person sdrtg ghytui; 07.04.2019
comment
спасибо, я все понял, просто хочу прояснить временную сложность :-) - person sdrtg ghytui; 07.04.2019
comment
Линейное время по количеству узлов. - person user2357112 supports Monica; 07.04.2019
comment
Хорошая идея. Но имейте в виду, что дерево имеет ненаправленные ребра. Так что используйте посещаемый массив при обходе! - person nishant_boro; 12.04.2019
comment
@user2357112 user2357112 любые идеи по этой проблеме дерева: - stackoverflow.com/questions/56549158/ - person sdrtg ghytui; 12.06.2019

Идея состоит в том, чтобы проанализировать дерево и посмотреть, какое поддерево можно удалить, чтобы прибыль увеличилась по сравнению с его начальным состоянием. Сделайте этот анализ для каждого узла, прежде чем что-либо удалять. Затем удалите поддеревья, которые больше всего увеличивают прибыль. Мы можем сделать это в два прохода:

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) Обходя дерево в ширину, удаляем узел i (и его поддерево), если G(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]
person Gilles-Philippe Paillé    schedule 05.04.2019
comment
Но как нам удалить поддерево? Ограничения проблемы жесткие, и данное дерево не является бинарным деревом. - person Firex Firexo; 05.04.2019
comment
Я предположил, что это бинарное дерево, поскольку он использовал ключевое слово. Что вы подразумеваете под жесткими ограничениями? Удаление узла зависит от структуры данных, но обычно сначала удаляются два потомка, а затем узел. Удаление детей рекурсивно уничтожит их собственных детей и т. д. - person Gilles-Philippe Paillé; 05.04.2019
comment
Решение мне пока непонятно. Дерево не является двоичным, и структура данных для реализации такого дерева также неясна. не могли бы вы предоставить лучшее решение со структурой данных и кодом обхода. - person Ujjwal Roy; 08.04.2019
comment
@UjjwalRoy Поскольку проблема была абстрактной без какого-либо конкретного языка, я не видел смысла в предоставлении кода. Лично я считаю, что особенно для таких проблем полезнее сосредоточиться на идее, а не на технических вещах. Но если это прояснит ситуацию, я могу предоставить немного кода. Решение можно легко распространить на небинарные деревья, я просто предположил, что оно бинарное из-за тега и что нигде не указано, что оно не бинарное. Я изменю решение. - person Gilles-Philippe Paillé; 08.04.2019