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; }