Enlace del título: https://vijos.org/d/newbzoj/p/590c9893d3d8a132109937a3
De hecho, el significado es muy simple, primero mire: dé un árbol de N puntos, encuentre un punto, cuando el árbol arraigado en este punto, la suma de la profundidad de todos los puntos es la más grande
Si es violento, debe ser TLE.
Entonces debemos encontrar un camino.
Recuerdo una pregunta que optimizó n veces DFS a 2 veces DFS
¿Esta pregunta está bien?
Podemos pensarlo.
La respuesta es si.
Echa un vistazo a la idea:
Primero, todos los puntos son iguales al punto del árbol primario + el punto del árbol secundario.
Entonces solo pide la acumulación de los dos;
La profundidad total del subárbol es realmente fácil de encontrar, es decir, simplemente agregue la profundidad total del hijo a + tamaño;
El árbol principal es un poco problemático, porque necesita algo de preprocesamiento, por lo que se resuelve en la segunda búsqueda profunda;
Para un punto, el árbol padre de este punto es [padre + árbol padre del padre + árbol hijo del hermano];
Luego agréguelos por separado: solo
preste atención para impulsar la fórmula;
La complejidad temporal O (n)
tiene solo unos pocos detalles:
1. La fórmula debe calcularse (sumar y restar el mismo elemento y no eliminarlo ... de lo contrario no puede ajustarlo ...)
2. Esta pregunta requiere mucho tiempo
Detrás está el código.
Se agregaron algunas notas.
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 const int maxn = 1000005 ; 6 usando el espacio de nombres estándar; 7 typedef largo largo ll; 8 int n, no, a [maxn << 1 ], siguiente [maxn << 1 ], head [maxn], cnt; 9 ll sum [maxn], tamaño [maxn], fas [maxn], ans; 10 void add ( int x, int y) { 11 a [++ cnt] = y; siguiente [cnt] = head [x]; head [x] =cnt; 12 } 13 void DFS1 ( int x, int pre) { 14 size [x] = 1 ; int i, y; // size es el tamaño del subárbol, incluyendo x 15 para (i = head [x]; i ; i = siguiente [i]) { 16 if ((y = to [i])! = pre) { 17 DFS1 (y, x); 18 tamaño [x] + = tamaño [y]; 19 suma [x] + = suma [y] + tamaño [y]; // suma es la suma de profundidad, pero no incluye x 20 } 21 } 22 } 23 nulo DFS2 (int x, int pre) { 24 int i, y; 25 if (x! = 1 ) fas [x] = fas [pre] + n-size [pre] + sum [pre] -sum [x] -size [ x] + tamaño [pre] -size [x] -1 + 1 ; 26 // fas [pre] + n-size [pre] es la primera parte 27 // sum [pre] -sum [x] -size [x ] + tamaño [pre] -size [x] -1 es la segunda parte 28 // 1 es la tercera parte 29 // La fórmula debe entenderse bien 30 if (ans <fas [x] + sum [x]) { // fas es el árbol padre y 31 ans = fas [x] + suma [x]; 32 no = x; 33 } 34 más si (ans == fas [x] + suma [x]) no = min (no, x); 35 para (i = cabeza [x]; i; i = siguiente [i]) { 36 if ((y = a [i])! = Pre) { 37 DFS2 (y, x); 38 } 39 } 40 } 41 int main () { 42 // freopen ("a.in", "r", stdin); 43 scanf ( " % d " , & n); 44 para ( int i = 1 ; i <n; i ++ ) { 45 int x, y; scanf ( " % d% d" , & x, & y); 46 add (x, y); add (y, x); 47 } 48 DFS1 ( 1 , 0 ); DFS2 ( 1 , 0 ); 49 printf ( " % d \ n " , no); 50 devuelve 0 ; 51 }