Comentário OBOI 2023 Segunda Fase – Problema “Bonsai”

por

Comentário por Henrique Vianna

Conhecimento prévio necessário:

 

Perceba que o enunciado se resume ao seguinte: Dada uma árvore $$T$$ em que os vértices possuem valores $$v[i]$$ (que podem inclusive ser negativos), maximize $$\sum_{u \in T}v[u]$$ após a remoção de até $$K$$ vértices, juntos às suas respectivas subárvores. Na resolução desse exercício, analisaremos cada uma das parciais, antes de chegar à solução final.

 

Parcial 1: A árvore é uma linha, ou seja, $$u[i] = i, v[i] = i + 1$$  $$\forall 1 \leq i \leq N – 1$$.

Nessa parcial, podemos imaginar a a árvore como um vetor, em que as operações que podemos fazer é remover um sufixo seu. Perceba entretanto, que o valor de $$K$$ é irrelevante: sempre existe uma solução ótima em que exatamente um sufixo é removido, podendo esse ser nulo. Por consequência, sempre manteremos um prefixo desse vetor, ou seja, a resposta é simplesmente a maior soma de prefixo de $$T$$.

 

Parcial 2: $$1 \leq N \leq 10^3$$ e $$1 \leq K \leq 100$$

Para resolver essa parcial, faremos uso de uma dp, sendo que:

$$dp[u][j]$$ é o minimo que consigo remover com exatamente $$j$$ operações entre os vértices da subárvore de $$u$$.

A recorrência dessa dp é relativamente simples. Faremos uso de uma segunda dp, $$dp2$$, para nos auxiliar nessa recorrência:

$$dp2[i][j]$$ é o minimo que consigo remover em $$j$$ operações considerando os $$i$$ primeiros filhos de $$u$$.

A recorrência de $$dp2[i][j]$$ é bastante similar à DP clássica da Knapsack: deve-se brutar, para o filho atual, quantas operações serão feitas dentro de sua subárvore. Chamaremos esse numero de $$c$$. Sendo assim:

$$dp2[i][j] = min(dp2[i – 1][j], dp2[i – 1][j – c] + dp[v][c])$$, tal que $$1 \leq c \leq j$$

Ao final, para termos os valores de $$dp[u][j]$$ de fato, basta fazermos:

$$dp[u][j] = dp2[f][j]$$, sendo $$f$$ o numero de filhos de $$u$$.

A resposta é simplesmente $$\sum_{i= 1}^{N}v[i] – min(dp[1][j])$$, com $$1 \leq j \leq K$$.

 

Parcial 2: Sem restrições adicionais.

A $$dp$$ acima, apesar de ser suficiente para a parcial 2, não é rápida o suficiente para obter-se $$100$$ pontos, haja vista sua complexidade de $$\mathcal{O}(N*K^2)$$. Precisamos, portanto, otimizá-la. Uma maneira inteligente de fazer isso é “linearizar” a árvore, fazendo uma $$dp$$ similar a essa em seu Euler Tour. Para tanto, basta calcularmos o $$tin$$ e $$tout$$ de cada um dos vértices numa $$dfs$$ inicial. Calcularemos a $$dp$$ nos vértices ordenados por $$tin$$. Define-se:

$$dp[i][j]$$ é o minimo que consigo remover com exatamente $$j$$ operações entre os  $$i$$ últimos vértices do Euler Tour.

Vale notar que estamos calculando a nossa $$dp$$ no sufixo, ou seja, passando do ultimo vértice do Euler Tour ao primeiro. A recorrência, portanto, é dada por:

$$dp[i][j] = min(dp[i + 1][j],dp[tout[tour[i]+1]][j-1]+sub[tour[i])$$, sendo que $$sub[u]$$ guarda a soma dos $$v[i]$$ na subárvore de $$u$$.

A resposta é calculada da mesma forma que na parcial $$2$$. Sendo assim, conseguimos resolver o problema em $$\mathcal{O}(N*K)$$.

Para melhor compreensão, confira o código aqui.