You are given a tree (a connected graph without cycles) with n vertices.
Consider a fixed integer k. Then, the graph Gk is an undirected graph with n vertices, where an edge between vertices u and v exists if and only if the distance between vertices u and v in the given tree is at least k.
For each k from 1 to n, print the number of connected components in the graph Gk.
Input
The first line contains the integer n (2≤n≤105) — the number of vertices in the graph.
Each of the next n−1 lines contains two integers u and v (1≤u,v≤n), denoting an edge between vertices u and v in the tree. It is guaranteed that these edges form a valid tree.
Output
Output n integers: the number of connected components in the graph Gk for each k from 11 to n.
Examples
input
Copy
6
1 2
1 3
2 4
2 5
3 6
output
Copy
1 1 2 4 6 6
input
Copy
5
1 2
2 3
3 4
3 5
output
Copy
1 1 3 5 5
Note
In the first example: If k=1, the graph has an edge between each pair of vertices, so it has one component. If k=4, the graph has only edges 4↔6 and 5↔6, so the graph has 4 components.
In the second example: when k=1 or k=2 the graph has one component. When k=3 the graph Gk splits into 3 components: one component has vertices 1, 4 and 5, and two more components contain one vertex each. When k=4 or k=5 each vertex is a separate component.
思路:树上问题手足无措的时候,可以拿一些比较特殊的树去思考:比如一条链。如果要在一条链上求上述问题,很显然k从大到小倒着求是好实现的。
代码:
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
//找到距离 u 最远的顶点 v
int dfs(int u, int fa = -1)
{
int v = u;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
dis[j] = dis[u] + 1;
int t = dfs(j, u);
if(dis[v] < dis[t]) v = t;
}
return v;
}
void get_max_dis()
{
dis[1] = 0;
//距离 1 最远的 u
int u = dfs(1, -1);
//距离 u 最远的 v
//同时算出其他点到 u 的距离
//u、v即为一条直径的两个端点
dis[u] = 0;
int v = dfs(u, -1);
//更新
for(int i = 1; i <= n; i++) maxDis[i] = max(maxDis[i], dis[i]);
//计算其他点到 v 的距离
dis[v] = 0;
dfs(v, -1);
//更新
for(int i = 1; i <= n; i++) maxDis[i] = max(maxDis[i], dis[i]);
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; i++) h[i] = -1;
for(int i = 1; i <= n - 1; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
//预处理每个点到其他点的最大距离
get_max_dis();
int mxD = 0;
//更新cnt数组
for(int i = 1; i <= n; i++)
{
mxD = max(mxD, maxDis[i]);
cnt[maxDis[i]]++;
}
//前缀和
for(int i = 1; i <= mxD; i++) s[i] = s[i - 1] + cnt[i];
for(int k = 1; k <= n; k++)
{
if(k > mxD) ans[k] = n;
else ans[k] = n - (s[mxD] - s[k - 1]) + 1;
}
for(int k = 1; k <= n; k++)
cout << ans[k] << (k != n ? " " : endl);
}