Todavía DFS-new_bzoj Sta

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 }

 

Supongo que te gusta

Origin www.cnblogs.com/DZN2004/p/12686227.html
Recomendado
Clasificación