Skip to Content

Tree Distances I

Solución 1

Descrita en CPH 14.3.

#include <bits/stdc++.h> using namespace std; vector<int> adj[200001]; int firstMax[200001]; // to store first-max length. int secondMax[200001]; // to store second-max length. int c[200001]; // to store child for path of max length. // calculate for every node x the maximum // length of a path that goes through a child of x void dfs(int v, int p) { firstMax[v] = 0; secondMax[v] = 0; for (auto x : adj[v]) { if (x == p) continue; dfs(x, v); if (firstMax[x] + 1 > firstMax[v]) { secondMax[v] = firstMax[v]; firstMax[v] = firstMax[x] + 1; c[v] = x; } else if (firstMax[x] + 1 > secondMax[v]) { secondMax[v] = firstMax[x] + 1; } } } // calculate for every node x the // maximum length of a path through its parent p void dfs2(int v, int p) { for (auto x : adj[v]) { if (x == p) continue; if (c[v] == x) { if (firstMax[x] < secondMax[v] + 1) { secondMax[x] = firstMax[x]; firstMax[x] = secondMax[v] + 1; c[x] = v; } else { secondMax[x] = max(secondMax[x], secondMax[v] + 1); } } else { secondMax[x] = firstMax[x]; firstMax[x] = firstMax[v] + 1; c[x] = v; } dfs2(x, v); } } int main() { FIO; int n, u, v; cin >> n; for (int i = 0; i < n - 1; i++) { cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } dfs(1, -1); dfs2(1, -1); for (int i = 1; i <= n; i++) { cout << firstMax[i] << " "; } return 0; }
import java.io.*; import java.util.*; public class TreeDistancesI { static ArrayList<Integer>[] adj; static int MAX_N = 200000; static int[] firstMax = new int[MAX_N + 1]; // to store first-max length. static int[] secondMax = new int[MAX_N + 1]; // to store second-max length. static int[] c = new int[MAX_N + 1]; // to store child for path of max length. public static void dfs(int v, int p) { firstMax[v] = 0; secondMax[v] = 0; for (int x : adj[v]) { if (x == p) continue; dfs(x, v); if (firstMax[x] + 1 > firstMax[v]) { secondMax[v] = firstMax[v]; firstMax[v] = firstMax[x] + 1; c[v] = x; } else if (firstMax[x] + 1 > secondMax[v]) { secondMax[v] = firstMax[x] + 1; } } } public static void dfs2(int v, int p) { for (int x : adj[v]) { if (x == p) continue; if (c[v] == x) { if (firstMax[x] < secondMax[v] + 1) { secondMax[x] = firstMax[x]; firstMax[x] = secondMax[v] + 1; c[x] = v; } else { secondMax[x] = Math.max(secondMax[x], secondMax[v] + 1); } } else { secondMax[x] = firstMax[x]; firstMax[x] = firstMax[v] + 1; c[x] = v; } dfs2(x, v); } } public static void main(String[] args) { Kattio io = new Kattio(); int n, u, v; n = io.nextInt(); adj = new ArrayList[n + 1]; for (int x = 0; x < adj.length; x++) { adj[x] = new ArrayList(); } for (int i = 0; i < n - 1; i++) { u = io.nextInt(); v = io.nextInt(); adj[u].add(v); adj[v].add(u); } dfs(1, -1); dfs2(1, -1); for (int i = 1; i <= n; i++) { io.print(firstMax[i] + " "); } io.close(); } // CodeSnip{Kattio} }

Solución 2

Computamos un diámetro del árbol como describe el algoritmo 2 aquí. Una vez que tenemos un diámetro (a,b)(a,b), imprimimos max(dist(a,i),dist(b,i))\max(dist(a,i),dist(b,i)) para cada nodo ii.

#include <bits/stdc++.h> using namespace std; // dist[0][i] = distance from node a to node i // dist[1][i] = distance from node b to node i int dist[2][200000]; vector<int> adj[200000]; int dfs(int u, int p, int d, int i) { dist[i][u] = d; int opt = -1; for (int v : adj[u]) { if (v != p) { int x = dfs(v, u, d + 1, i); if (opt == -1 || dist[i][x] > dist[i][opt]) opt = x; } } return opt == -1 ? u : opt; } int main() { int n; cin >> n; for (int i = 0; i < n - 1; i++) { int a, b; cin >> a >> b; --a; --b; adj[a].push_back(b); adj[b].push_back(a); } // first, find node a by finding the farthest node from an arbitrary node x int mxNode = dfs(0, 0, 0, 0); // then, find node b (this step also computes distance from a to every other // node) int mxNode2 = dfs(mxNode, mxNode, 0, 0); // finally, compute the distance from b to every other node dfs(mxNode2, mxNode2, 0, 1); for (int i = 0; i < n; i++) { cout << max(dist[0][i], dist[1][i]) << " \n"[i == n - 1]; } return 0; }