Delegation
Explicación
Primero, notemos que si no es un divisor de , entonces las aristas nunca se pueden particionar de forma pareja. Así, solo necesitamos revisar los divisores de .
Podemos enraizar el árbol de forma arbitraria en el nodo . Sea la longitud del camino que pasa por el nodo y cuya longitud todavía no llegó a . Como solo existe camino así, todos los demás caminos que provienen de los subárboles de deben emparejarse de forma pareja.
Para cada nodo tal que es hijo del nodo , debe existir otro nodo tal que para completar el camino. Si no existe tal , entonces guardamos la longitud actual del camino en , pero solo puede haber un así.

En el árbol de arriba, supongamos . Entonces , , y . Como hay dos caminos de longitud y solo uno de longitud , nos queda un camino de longitud , así que .
Se puede demostrar que el número máximo de divisores de un entero hasta las restricciones de será lo suficientemente pequeño como para ejecutar un algoritmo de tiempo lineal por cada divisor.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
vector<int> g[N];
int to_be_merged[N];
bool dfs(int node, int p, int k) {
// contamos la longitud del camino aún no fusionado en los subárboles
map<int, int> to_be_merged_count;
for (int i : g[node]) {
if (i == p) { continue; }
if (!dfs(i, node, k)) { return false; }
int cur_merge = to_be_merged[i] + 1;
if (cur_merge != k) { to_be_merged_count[cur_merge]++; }
}
/*
* todos los subárboles deben emparejarse excepto uno, donde la longitud
* del camino se guarda en to_be_merged[node]
*/
for (auto [key, value] : to_be_merged_count) {
if (key == k - key) {
// fusionamos caminos de longitud k / 2
if (value % 2 == 1) {
// hay un camino sobrante
if (to_be_merged[node]) { return false; }
to_be_merged[node] = key;
}
} else {
// fusionamos caminos cuyas longitudes suman k
if (value > to_be_merged_count[k - key]) {
// hay más de un camino o ya encontramos un camino
if (value - to_be_merged_count[k - key] > 1 || to_be_merged[node]) {
return false;
}
// guardamos el camino sobrante
to_be_merged[node] = key;
}
}
}
return true;
}
int main() {
ifstream cin("deleg.in");
int n;
cin >> n;
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
g[--u].push_back(--v);
g[v].push_back(u);
}
ofstream cout("deleg.out");
for (int k = 1; k <= n - 1; k++) {
if ((n - 1) % k != 0) {
cout << 0;
} else {
fill(to_be_merged, to_be_merged + n, 0);
cout << dfs(0, 0, k);
}
}
}