Problem: 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 ∈ 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 ≤ n ≤ 5 ⋅ 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 ≤ u_i, v_i ≤ 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.

Examples

Input


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 ≥ 1. 



In the second sample there is an almost-2-uniform set of size 4, and that is \{2, 3, 5, 6\}.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
int maxv[2000005];
void update(int o, int l, int r, int from, int to, int v) {
  if (from > to) return;
  if (l >= from && r <= to) {
    maxv[o] = max(maxv[o], v);
    return;
  }
  if (from <= (l + r) / 2) update(o << 1, l, (l + r) / 2, from, to, v);
  if (to > (l + r) / 2) update(o << 1 | 1, (l + r) / 2 + 1, r, from, to, v);
}
int query(int o, int l, int r, int p) {
  int ans = maxv[o];
  if (l == r) return ans;
  if (p <= (l + r) / 2)
    ans = max(ans, query(o << 1, l, (l + r) / 2, p));
  else
    ans = max(ans, query(o << 1 | 1, (l + r) / 2 + 1, r, p));
  return ans;
}
struct Edge {
  int to;
  int nxt;
} e[1000005];
struct Node {
  int dep;
  int in;
} tmp[1000005];
int n, m, edgenum, head[500005], pa[500005], dep[500005], d[500005],
    max1[500005], max2[500005], ans[500005];
int a[500005], top, _f[2000005], *f[2000005], tot;
int num[500005];
priority_queue<int> q, del;
bool cmp(Node a, Node b) { return a.dep < b.dep; }
void add(int u, int v) {
  e[++edgenum].to = v;
  e[edgenum].nxt = head[u];
  head[u] = edgenum;
}
void dfs1(int node) {
  f[node] = _f + tot;
  tot += d[node] + 2;
  dep[node] = dep[pa[node]] + 1;
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node]) continue;
    pa[to] = node;
    dfs1(to);
    if (max1[to] + 1 > max1[node]) {
      max2[node] = max1[node];
      max1[node] = max1[to] + 1;
    } else if (max1[to] + 1 > max2[node])
      max2[node] = max1[to] + 1;
  }
}
void dfs2(int node) {
  top = 0;
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node]) continue;
    a[++top] = max1[to] + 1;
  }
  if (pa[node]) {
    if (max1[pa[node]] == max1[node] + 1)
      a[++top] = max2[pa[node]] + 1;
    else
      a[++top] = max1[pa[node]] + 1;
  }
  a[++top] = 0;
  sort(a + 1, a + top + 1);
  for (int i = 1; i <= top; i++) f[node][top - i + 1] = a[i];
  for (int i = 1; i <= top; i++) {
    ans[f[node][i] * 2] = max(ans[f[node][i] * 2], i);
    if (f[node][i - 1] != f[node][i])
      ans[f[node][i] * 2 + 1] = max(ans[f[node][i] * 2 + 1], i);
  }
  top = 0;
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node]) {
      tmp[++top].in = node;
      if (max1[pa[node]] == max1[node] + 1)
        tmp[top].dep = max2[pa[node]] + 1;
      else
        tmp[top].dep = max1[pa[node]] + 1;
      continue;
    }
    tmp[++top].in = node;
    tmp[top].dep = max1[to] + 1;
    for (int hd = head[to]; hd; hd = e[hd].nxt) {
      int to2 = e[hd].to;
      if (to2 == node) continue;
      tmp[++top].in = to;
      tmp[top].dep = max1[to2] + 1;
    }
  }
  while (!q.empty()) q.pop();
  while (!del.empty()) del.pop();
  sort(tmp + 1, tmp + top + 1, cmp);
  num[node] = d[node];
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node]) continue;
    num[to] = d[to] - 1;
    q.push(num[to]);
  }
  for (int i = 1; i <= top; i++) {
    if (tmp[i].in == node) {
      while (!q.empty() && !del.empty() && q.top() == del.top())
        q.pop(), del.pop();
      if (q.empty()) continue;
      update(1, 1, n, 1, tmp[i].dep, num[node] - 1 + q.top());
      num[node]--;
    } else {
      update(1, 1, n, 1, tmp[i].dep, num[node] - 1 + num[tmp[i].in]);
      del.push(num[tmp[i].in]);
      num[tmp[i].in]--;
      if (num[tmp[i].in]) q.push(num[tmp[i].in]);
    }
  }
  if (pa[node]) {
    int v = 0;
    if (max1[node] + 1 == max1[pa[node]])
      v = max2[pa[node]];
    else
      v = max1[pa[node]];
    if (v + 1 > max1[node]) {
      max2[node] = max1[node];
      max1[node] = v + 1;
    } else if (v + 1 > max2[node])
      max2[node] = v + 1;
  }
  for (int hd = head[node]; hd; hd = e[hd].nxt) {
    int to = e[hd].to;
    if (to == pa[node]) continue;
    dfs2(to);
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    add(u, v);
    add(v, u);
    d[u]++, d[v]++;
  }
  for (int i = 1; i <= n; i++) ans[i] = 1;
  dfs1(1);
  dfs2(1);
  for (int i = n; i >= 1; i--) ans[i] = max(ans[i], ans[i + 1]);
  for (int i = 1; i <= n; i++) {
    if (i & 1)
      printf("%d ", ans[i]);
    else
      printf("%d ", max(ans[i], query(1, 1, n, i / 2)));
  }
  return 0;
}