Let $G$ be a simple graph. Let $W$ be a non-empty subset of vertices. Then $W$ is almost-$k$-uniform if for each pair of distinct vertices $u,v \in W$ the distance between $u$ and $v$ is either $k$ or $k+1$.
You are given a tree on $n$ vertices. For each $i$ between $1$ and $n$, find the maximum size of an almost-$i$-uniform set.Input
The first line contains a single integer $n$ ($2 \leq n \leq 5 \cdot 10^5$) – the number of vertices of the tree.
Then $n-1$ lines follows, the $i$-th of which consisting of two space separated integers $u_i$, $v_i$ ($1 \leq u_i, v_i \leq n$) meaning that there is an edge between vertices $u_i$ and $v_i$.
It is guaranteed that the given graph is tree.Output
Output a single line containing $n$ space separated integers $a_i$, where $a_i$ is the maximum size of an almost-$i$-uniform set.Examplesinput
5 1 2 1 3 1 4 4 5
output
4 3 2 1 1
input
6 1 2 1 3 1 4 4 5 4 6
output
4 4 2 1 1 1
Note
Consider the first example.
- The only maximum almost-$1$-uniform set is $\{1, 2, 3, 4\}$.
- One of the maximum almost-$2$-uniform sets is or $\{2, 3, 5\}$, another one is $\{2, 3, 4\}$.
- A maximum almost-$3$-uniform set is any pair of vertices on distance $3$.
- Any single vertex is an almost-$k$-uniform set for $k \geq 1$.
In the second sample there is an almost-$2$-uniform set of size $4$, and that is $\{2, 3, 5, 6\}$.
Solution:
#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
string to_string(pair<A, B> p);
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);
string to_string(const string& s) {
return '"' + s + '"';
}
string to_string(const char* s) {
return to_string((string) s);
}
string to_string(bool b) {
return (b ? "true" : "false");
}
string to_string(vector<bool> v) {
bool first = true;
string res = "{";
for (int i = 0; i < static_cast<int>(v.size()); i++) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(v[i]);
}
res += "}";
return res;
}
template <size_t N>
string to_string(bitset<N> v) {
string res = "";
for (size_t i = 0; i < N; i++) {
res += static_cast<char>('0' + v[i]);
}
return res;
}
template <typename A>
string to_string(A v) {
bool first = true;
string res = "{";
for (const auto &x : v) {
if (!first) {
res += ", ";
}
first = false;
res += to_string(x);
}
res += "}";
return res;
}
template <typename A, typename B>
string to_string(pair<A, B> p) {
return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
cerr << " " << to_string(H);
debug_out(T...);
}
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
vector<vector<int>> g;
vector<int> down;
vector<int> order;
vector<int> pv;
void Dfs(int v) {
order.push_back(v);
down[v] = 0;
for (int u : g[v]) {
if (u == pv[v]) {
continue;
}
pv[u] = v;
Dfs(u);
down[v] = max(down[v], down[u] + 1);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
g.resize(n);
for (int i = 0; i < n - 1; i++) {
int x, y;
cin >> x >> y;
--x; --y;
g[x].push_back(y);
g[y].push_back(x);
}
down.resize(n);
order.clear();
pv.resize(n);
pv[0] = -1;
Dfs(0);
vector<int> ans(n + 1, 1);
vector<int> up(n, 0);
vector<int> children;
vector<int> cc;
vector<vector<int>> vcc(n);
for (int it = 0; it < (int) order.size(); it++) {
children.clear();
cc.clear();
int v = order[it];
for (int u : g[v]) {
if (u == pv[v]) {
continue;
}
children.push_back(u);
cc.push_back(down[u] + 1);
}
cc.push_back(up[v]);
if (up[v] != 0) {
cc.push_back(0);
}
sort(cc.rbegin(), cc.rend());
// debug(cc);
int sz = (int) cc.size();
for (int i = 1; i < sz - 1; i++) {
ans[2 * cc[i] - 1] = max(ans[2 * cc[i] - 1], i + 1);
}
for (int i = 1; i < sz; i++) {
if (cc[i] < cc[i - 1]) {
ans[2 * cc[i] + 1] = max(ans[2 * cc[i] + 1], i + 1);
}
}
for (int i = 1; i < sz - 1; i++) {
ans[2 * cc[i]] = max(ans[2 * cc[i]], i + 1);
}
if (pv[v] != -1) {
int id_up = 0;
while (cc[id_up] != up[v]) {
++id_up;
}
int first = -1;
int second = -1;
for (int i = 0; i < sz; i++) {
if (i == id_up) {
continue;
}
if (first == -1) {
first = cc[i];
} else {
second = cc[i];
break;
}
}
int ptr = 0;
for (int h = second; h >= 1; h--) {
while (ptr < sz && cc[ptr] >= h) {
++ptr;
}
int realz = ptr - (id_up < ptr);
auto iter = lower_bound(vcc[pv[v]].begin(), vcc[pv[v]].end(), h);
realz += (int) (vcc[pv[v]].end() - iter) - 1;
ans[2 * h] = max(ans[2 * h], realz);
}
}
vcc[v] = cc;
reverse(vcc[v].begin(), vcc[v].end());
for (int u : children) {
if (cc[0] == down[u] + 1) {
up[u] = cc[1] + 1;
} else {
up[u] = cc[0] + 1;
}
}
}
for (int i = n; i >= 3; i--) {
ans[i - 2] = max(ans[i - 2], ans[i]);
}
for (int i = 1; i <= n; i++) {
if (i > 1) {
cout << " ";
}
cout << ans[i];
}
cout << '\n';
return 0;
}