Autor del Problema: | Timosh |
Preparado por: | Hasan Saleh (MathModel) |
Editado por: | Hasan Saleh (MathModel) |
Solución
Llamamos a un nodo una hoja si tiene grado . Sea el número total de hojas en el árbol.
Raíz el árbol en . Para cada nodo , sea el número de hojas dentro del subárbol de (con respecto a esta raíz). Podemos calcular mediante un DFS:
Considera cualquier arista donde es el padre de . Si cortamos esta arista, aparecen dos componentes:
- El lado tiene hojas, pero el grado de disminuye en . Un nodo se convierte en hoja si y solo si su grado era , y una hoja deja de ser hoja si y solo si su grado era . Por lo tanto, el conteo de hojas en el lado después del corte es
- El lado tiene L-s[v] hojas, y pierde una arista incidente, por lo que su grado también disminuye en . Así, el conteo de hojas en el lado después del corte es
Una arista es equilibrada si A=B. Podemos calcular L=s[1] desde el primer DFS, luego en un segundo DFS sobre las aristas padre-hijo, probar la igualdad anterior y contar cuántas veces se cumple.
Esquema de Corrección
Cortar cambia el estado de hoja solo en los extremos y (todos los demás mantienen el mismo grado), por lo que ajustar por +[\deg=2]-[\deg=1] es tanto necesario como suficiente. Dado que y L-s[v] cuentan hojas estrictamente dentro de cada lado antes de considerar los cambios de grado de los extremos, A=B caracteriza exactamente las aristas equilibradas.
Complejidad por prueba (dos recorridos DFS).
#include <bits/stdc++.h>
using namespace std;
#define int int64_t
using vi=vector<int>;
void solve(){
int n;cin>>n;
vector<vi> g(n+1);
for(int i=0,u,v;i<n-1;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> s(n+1);
vector<char> vis(n+1,0);
auto tour= [&](auto self,int v,int p)->void{
vis[v]=1;
s[v]+= (int)g[v].size()==1;
for(int u:g[v]) if(u!=p) self(self,u,v), s[v]+=s[u];
};
tour(tour,1,0);
int L=s[1], ans=0;
fill(vis.begin(),vis.end(),0);
auto dfs= [&](auto self,int v,int p)->void{
vis[v]=1;
for(int u:g[v]) if(u!=p){
int A = s[u] + ((int)g[u].size()==2) - ((int)g[u].size()==1);
int B = L - s[u] + ((int)g[v].size()==2) - ((int)g[v].size()==1);
ans += (A==B);
self(self,u,v);
}
};
dfs(dfs,1,0);
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t; if(!(cin>>t)) return 0;
while(t--) solve();
return 0;
}