题目链接:https://codeforces.com/contest/1805/problem/D
思路:先找到树的直径,然后寻找到树的直径两端距离小于等于k的点,即为孤立点;树的直径可用两次dfs求出
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+5;
int n,m;
int dist[N], d[N];
int c=0;
vector<int> e[N];
void dfs(int u, int fa) {
for(auto v : e[u]) {
if(v == fa) continue;
dist[v]=dist[u]+1;
if(dist[v]>dist[c])c=v;
dfs(v, u);
}
}
void solve()
{
int a, b;
cin >> n;
m = n - 1;
for(int i = 1; i <= m; i ++ ) {
cin >> a >> b;
e[a].push_back(b), e[b].push_back(a);
}
dist[c]=0;
dist[1]=0;
dfs(1, 0);
dist[c]=0;
dfs(c,0);
for(int i = 1; i <= n; i ++ ) {
d[i] = dist[i];
}
dist[c] = 0;
dfs(c, 0);
for(int i = 1; i <= n; i ++ ) {
d[i] = max(d[i], dist[i]) ;
}
// 每个点的距离我们取距直径两端的最大值
int ans = 0, now = 1;
sort(d + 1, d + n + 1);
for(int i = 1; i <= n; i ++ ) {
while(now <= n && d[now] < i) {
now ++ , ans ++ ;
}
// 如果 d[now] < i,说明这个点无法加入直径两端所在连通块
cout << min(ans + 1, n) << " ";
}
}
signed main()
{
solve();
}