Aula por Arthur Lobo
Conhecimento prévio necessário:
Assim como podemos usar DP (Dynamic Programming) para resolver problemas em sequências lineares (como o problema do troco), também podemos usá-las para resolver problemas em árvores.
Nos problemas de Programação Dinâmica em árvore, geralmente vamos enraizar a árvore em algum vértice arbitrário (comummente escolhemos o 1) e a DP vai guardar informações sobre cada subárvore do grafo. Ou seja, vai guardar alguma informação sobre a subárvore de
, mas normalmente vão ter mais estados do que apenas qual a subárvore. Mas considerando que existe apenas um estado (a raiz da subárvore), vai ser nesse formato:
- Caso base: Toda DP precisa ter um caso base. No caso de DP em árvore esse caso vão ser as folhas (vértices que não tem filhos). Sempre conseguimos calcular o valor de
em
se
for uma folha.
- Transição: Para calcular o valor de
, vamos primeiro ter que calcular o valor da
de todos os filhos de
, e então calcular
baseado nesses valores. A exata transição sempre vai depender do problema.
- Resposta: Depois de calcular todas as
, a resposta do problema geralmente vai ser
(ou 1, se raiz for 1). Mas assim como a transição, isso vai depender do problema.
A ideia é que vai guardar alguma informação se estivermos olhando para uma árvore é que apenas a subárvore de
e, com a informação das subárvores dos filhos de
, podemos calcular
, fazendo isso das folhas até chegar na raiz.
Obs: Quando se referimos à subárvore de em uma árvore enraizada, estamos nos referindo à todo vértice
que passa por
no caminho até a raiz (incluindo o próprio
).
Motivação Inicial
Vamos imaginar o seguinte problema:
Dado uma árvore de vértices e
arestas, vértice
(
) tem
moedas. Você pode escolher um conjunto de vértices nessa árvore e pegar as moedas dos vértices nesse conjunto, mas tem um detalhe: não podem existir dois vértices adjacentes no conjunto. Diga qual é a maior soma de moedas de um conjunto válido.
Formalmente, qual o maior valor da soma tal que
é um subconjunto de vértices da árvore e não existem dois vértices adjacentes (ou seja, que são diretamente ligados por uma arestas) presentes nesse conjunto. Vale ressaltar que
não é um valor fixo, apenas o tamanho do conjunto.
Clique aqui para conferir o enunciado inteiro
Solução
A ideia nesse problema é fazermos uma DP em árvore com 2 estados: Um vai ser falando qual subárvore estamos vendo e o outro diz se a raiz está no conjunto escolhido ou não. Então a será:
= maior soma olhando apenas para a subárvore de
e
não é um dos vértices escolhidos. Ou seja, esse é o maior valor da soma
, tal que
é um subconjunto de vértices da subárvore de e
não está nesse subconjunto.
= maior soma olhando apenas para a subárvore de
e
é um dos vértices escolhidos. Ou seja, esse é o maior valor da soma
, tal que
é um subconjunto de vértices da subárvore de e
está nesse subconjunto.
Pare por alguns instantes e tente imaginar como seriam os casos base, as transições e a resposta dessa DP. Tentou? Então vamos lá:
Primeiro vamos imaginar para :
- Caso base: Como falado a cima, os casos bases da nossa DP serão as folhas. Se
é uma folha e não escolhemos ele para o subconjunto, então
.
- Transição: Primeiro temos que calcular o valor das DP todos os filhos de
. Depois de fazermos isso, vamos olhar para cada filho
de
. Já que o
não foi escolhido para estar no subconjunto, o
pode estar ou não nele, então podemos pegar o melhor valor entre
e
. Ou seja, se o
não foi escolhido para estar no subconjunto, então todas as subárvores dos filhos dele serão livres para ter ou não a raiz escolhida. Formalmente,
.
Agora para :
- Caso base: Se
é uma folha e escolhemos ele para o subconjunto, então
.
- Transição: Depois de calcularmos as DP dos filhos, vamos olhar para cada filho
de
. Já que o
foi escolhido para estar no subconjunto, o
não pode estar nele (pois
é adjacente à
), então somos obrigados a pegar
. Ou seja, se o
foi escolhido para estar no subconjunto, então todas as subárvores dos filhos dele serão obrigadas a não escolherem a raiz. Além disso, já que escolhemos a raiz, temos que adicionar
. Formalmente,
.
Lembrando que temos que calcular ambas as DP ao mesmo tempo, então na vamos calcular
e
. Agora a resposta será simplesmente o maior valor entre colocar a raiz (provavelmente o 1) e não colocá-lo. Ou seja
.
Código: