DP en árboles - Resolver para todas las raíces
| Hecho | Fuente | Nombre | Dificultad | Tags | Solución |
|---|---|---|---|---|---|
| CSES | Tree Distances I | Fácil | Tree, DFS | Solución |
Solución - Tree Distances I
| Fuente | Recurso | Notas |
|---|---|---|
| CPH | 14.3 - All Longest Paths |
Es una técnica común calcular dos arreglos de DP en algunos problemas de DP sobre árboles. Normalmente un arreglo de DP se encarga de calcular resultados dentro del subárbol con raíz en . El otro arreglo de DP calcula resultados fuera del subárbol con raíz en .
El problema foco nos pide hallar, para cada nodo, la distancia máxima a otro nodo. Podemos partir el problema en dos partes.
Definimos como la distancia máxima desde el nodo a cualquier nodo del subárbol con raíz en , y como la distancia máxima desde el nodo a cualquier nodo fuera del subárbol con raíz en . Entonces la respuesta para el nodo es .
- se puede calcular con un DFS, ya que , donde es un hijo de .
- también se puede calcular con un DFS como , donde y son ambos hijos de con .
Para calcular en tiempo lineal, podemos definir otro arreglo tal que sea la mayor distancia desde el nodo a cualquier nodo del subárbol con raíz en excluyendo el subárbol hijo que contribuyó a . Así, si se transiciona desde la rama con , . En caso contrario .
#include <bits/stdc++.h>
using namespace std;
vector<int> graph[200001];
int fir[200001], sec[200001], ans[200001];
void dfs1(int node = 1, int parent = 0) {
for (int i : graph[node])
if (i != parent) {
dfs1(i, node);
if (fir[i] + 1 > fir[node]) {
sec[node] = fir[node];
fir[node] = fir[i] + 1;
} else if (fir[i] + 1 > sec[node]) {
sec[node] = fir[i] + 1;
}
}
}
void dfs2(int node = 1, int parent = 0, int to_p = 0) {
ans[node] = max(to_p, fir[node]);
for (int i : graph[node])
if (i != parent) {
if (fir[i] + 1 == fir[node]) dfs2(i, node, max(to_p, sec[node]) + 1);
else dfs2(i, node, ans[node] + 1);
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
dfs1();
dfs2();
for (int i = 1; i <= n; i++) cout << ans[i] << ' ';
return 0;
}import java.io.*;
import java.util.*;
public class Main {
public static ArrayList<Integer> g[];
public static Pair maxl1[];
public static Pair maxl2[];
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
g = new ArrayList[N + 1];
maxl1 = new Pair[N + 1];
maxl2 = new Pair[N + 1];
for (int i = 0; i <= N; i++) {
g[i] = new ArrayList<Integer>();
maxl1[i] = new Pair(0, 0);
maxl2[i] = new Pair(0, 0);
}
for (int i = 1; i < N; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
g[a].add(b);
g[b].add(a);
}
dfs1(1, 0);
dfs2(1, 0);
for (int i = 1; i <= N; i++) { System.out.print(maxl1[i].f + " "); }
}
public static int dfs1(int i, int p) {
int ret = 0;
for (int next : g[i]) {
if (next != p) {
int c = dfs1(next, i);
ret = Math.max(ret, c + 1);
if (c + 1 > maxl1[i].f) {
maxl2[i] = maxl1[i];
maxl1[i] = new Pair(c + 1, next);
} else if (c + 1 > maxl2[i].f) {
maxl2[i] = new Pair(c + 1, next);
}
}
}
return ret;
}
public static void dfs2(int i, int p) {
if (p != 0) {
if (maxl1[p].s == i) {
if (maxl2[p].f + 1 > maxl1[i].f) {
maxl2[i] = maxl1[i];
maxl1[i] = new Pair(maxl2[p].f + 1, p);
} else if (maxl2[p].f + 1 > maxl2[i].f) {
maxl2[i] = new Pair(maxl2[p].f + 1, p);
}
} else {
if (maxl1[p].f + 1 > maxl1[i].f) {
maxl2[i] = maxl1[i];
maxl1[i] = new Pair(maxl1[p].f + 1, p);
} else if (maxl1[p].f + 1 > maxl2[i].f) {
maxl2[i] = new Pair(maxl1[p].f + 1, p);
}
}
}
for (int next : g[i]) {
if (next != p) dfs2(next, i);
}
}
static class Pair {
public int f, s;
public Pair(int f, int s) {
this.f = f;
this.s = s;
}
}
}Problemas
| Hecho | Fuente | Nombre | Dificultad | Tags | Solución |
|---|---|---|---|---|---|
| CF | Tree Painting | Fácil | DP | Solución | |
| AC | ★ Subtree | Normal | DP | Solución | |
| Balkan OI | 2017 - City Attractions | Normal | DP, Functional Graph | Solución | |
| Gold | Directory Traversal | Normal | DP, Tree | Solución | |
| APIO | ★ 2010 - Patrol | Difícil | DP, Casework | — | |
| IZhO | 2017 - Hard route | Difícil | DP | Solución | |
| APIO | 2014 - Beads | Muy difícil | DP, Casework | Solución | |
| CEOI | 2020 - Star Trek | Muy difícil | DP, Math | — | |
| Platinum | Cow At Large | Muy difícil | DP, Tree | Solución |