luoguP5536 【XR-3】核心城市
树的直径
\(dfs1\)求直径的一端点
\(dfs2\)求整个直径的长度,并保存下直径上的所有点
然后\(for\)一边 \(f\) 数组(保存下来的点),求出中点
\(dfs3\)用\(mid\)为根来统计所有节点的深度,并算出每个节点能到达的最大深度
然后求出相对深度,排序之后,前$ k$ 个 即满足题目要求,输出\(k + 1\) 就是答案
因为在做差求相对深度的时候没有\(+1\) ,所以答案最后要$+1 $
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int e[N*2],ne[N*2],h[N],idx,f[N],d[N],mx,pos,mxd[N],dd[N];
void add(int a,int b) {
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
bool cmp(int a,int b) {
return a > b;
}
void dfs1(int u,int fa) {// 求直径
if(mx < d[u]) mx = d[u],pos = u;
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(j == fa) continue;
d[j] = d[u] + 1;
dfs1(j,u);
}
}
void dfs2(int u,int fa) {
if(mx < d[u]) mx = d[u],pos = u;
for(int i = h[u]; ~i;i = ne[i]) {
int j = e[i];
if(j == fa) continue;
d[j] = d[u] + 1;
f[j] = u;// 记录直径上的点
dfs2(j,u);
}
}
void dfs3(int u,int fa) {
mxd[u] = d[u];
for(int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if(j == fa) continue;
d[j] = d[u] + 1;
dfs3(j,u);
mxd[u] = max(mxd[u],mxd[j]);
}
}
int main() {
int n,k;
memset(h,-1,sizeof h);
cin >> n >> k;
for(int i = 0;i < n - 1; ++i) {
int a,b;
cin >> a >> b;
add(a,b);
add(b,a);
}
dfs1(1,0);
memset(d,0,sizeof d);
mx = 0;
dfs2(pos,0);// 找直径
int mid = pos;
for(int i = 1;i <= (d[pos] + 1) / 2; ++i) mid = f[mid];
memset(d,0,sizeof d);
dfs3(mid,0);// 以中点为根,遍历树的深度,mxd[i] 代表i当前能走多深
for(int i = 1;i <= n; ++i) dd[i] = mxd[i] - d[i];// 当前i能走多深 减去 当前的深度,就得到了绝对深度
sort(dd + 1,dd + 1 + n,cmp);// 前 k 个城市联通 即可,第 k + 1即是答案
cout << dd[k + 1] + 1;// mxd - d 是距离,但是没有加1,比如 1 到 5 的距离是 5 - 1 + 1,不是 5 - 1
return 0;
}