Empezando a pensar que no es cuadrada del círculo por medio de un árbol, pensando muy confuso, pensé durante mucho tiempo para calmarse y encontrar a esta pregunta no es una cuestión sencilla para discutir clasificada Bueno ...
El sujeto no es difícil, discutir dos casos:
Ajuste el punto actual hasta un punto intermedio (punto)
- Después de entrar a partir de un subárbol a un hijo punto hijo intermedio en otro subárbol.
- Después de introducir el punto de partida desde subárbol de un hijo para el punto intermedio y todavía de nuevo el subárbol hijo (el equivalente de problemas de un niño)
- Luego de su hijo (puntos cuadrados) directamente se acumulan, el padre (puntos cuadrados) para deducir el impacto de la actual sub-árbol.
código:
#include <cstdio> #include <cstring> #include <algoritmo> #include <vector> #define N 200006 #define ll largo largo #define setIO (s) freopen (s ".En", "r", stdin) usando espacio de nombres std; vector <int> G [N]; ll ans; bordes int, tim, tot, n, m, fr, TAMAÑO; int hd [N << 1], a [N << 1], nex [N << 1], dfn [N], bajo [N], S [N], deg [N], tamaño [N]; ll g [N], F [N]; add void (int u, int v) { nex [++ bordes] = hd [u], hd [u] = bordes, a [bordes] = v; } Void Tarjan (int x) { dfn [x] = baja [x] = ++ tim; S [++ fr] = x; ++ TAMAÑO; for (int i = hd [x]; i; int y = a [i]; si (DFN [y]!) { Tarjan (y); bajo [x] = min (bajo [x], bajo [y]); si (bajo [y]> = dfn [x]) { ++ tot; G [x] .push_back (tot); G [tot] .push_back (x); ++ deg [tot]; para (p int = 0; p = y; - fr) { p = S [fr]; ++ deg [tot]; G [tot] .push_back (p); G [P] .push_back (tot); } } } Demás { Baja [x] = min (bajo [x], dfn [y]); } } } Dfs void (int x, ff int) { Tamaño [x] = (x <= n); for (int i = 0; i <G [x] .size (); ++ i) { int y = G [x] [i]; si (y == ff) continuar; dfs (y, x); tamaño [x] + = tamaño [y]; } } Void resolver (int x, int ff) { si (x <= n) { int cu = 0; for (int i = 0; i <G [x] .size (); ++ i) { int y = G [x] [i]; si (y == ff) cu = Tamaño Tamaño [x]; otro cu = tamaño [y]; } ans + = 1LL * cu * (tamaño-cu-1); } Si (ff) { ans + = g [ff] -1ll * tamaño [x] * Tamaño; Respuesta-= 1LL * tamaño [x] * (tamaño 2 tamaño * [x]); } } Más { for (int i = 0; i <G [x] .size (); ++ i) { int y = G [x] [i]; si (y == ff) continuar; F [x] + = 1LL * tamaño [y] * (tamaño [x] -size [y]); g [x] + = 1LL * tamaño [y] * (tamaño de tamaño [y]); } G [x] + = 1LL * tamaño [x] * (Tamaño Tamaño [x]); ans + = 1LL * F [x]; for (int i = 0; i <G [x] .size (); ++ i) if (! G [x] [i] = ff) resolver (G [x] [i], x); } Int main () { // setIO ( "input"); scanf ( "% d% d", y n, y m); tot = n; for (int i = 1; i <= m; ++ i) { int x, y; scanf ( "% d% d", y x, y y); añadir (x, y), añadir (y, x); } For (int i = 1; i <= n; ++ i) { si (dfn [i]!) { Tim = SIZE = fr = 0; Tarjan (i); dfs (i, 0); resolver (i, 0); } } Printf ( "% LLD \ n", ans); }