方法:首先找到最长的直径,即距离最长的两个点,然后通过深度优先遍历,得到每个节点到这两个点的距离,取其中较长的距离,然后对距离进行排序,再计算k从1到n的组成成分,当为1的时候只有一份,随着k的增大,到两个端点的最大距离小于k的点就需要分离,每一个点分离,组成成分就增加1,以此计算出所有的组成成分。
#include<bits/stdc++.h>
using namespace std;
vector<vector<int>> mp;
void dfs(int v, int p, int h, vector<int>& d) {
d[v] = h;
for (int i : mp[v]) {
if (i != p) dfs(i, v, h + 1, d);
}
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;
int x, y;
cin >> n;
mp = vector<vector<int>>(n + 1);
for (int i = 1; i < n; i++) {
cin >> x >> y;
mp[x].push_back(y); //使用邻接表存储图
mp[y].push_back(x);
}
vector<int> d1(n + 1), d2(n + 1);
dfs(1, -1, 0, d1);
int a = max_element(d1.begin(), d1.end()) - d1.begin(); //得到第一个端点
dfs(a, -1, 0, d1);
int b = max_element(d1.begin(), d1.end()) - d1.begin(); //得到距离第一个端点最远的第二个端点
dfs(b, -1, 0, d2);
for (int i = 1; i <= n; i++) {
d2[i] = max(d1[i], d2[i]); //得到所有节点到两个端点的最大距离
}
sort(d2.begin(), d2.end()); //对距离排序
int ans = 0;
for (int i = 1; i <= n; i++) {
while (ans < n && d2[ans] < i) { //删除距离小于K的路径,组成成分增大
ans++;
}
cout << ans << " ";
}
return 0;
}