P5536 树的直径
【XR-3】核心城市
题目描述
X 国有 \(n\) 座城市,\(n - 1\) 条长度为 \(1\) 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。
X 国国王决定将 \(k\) 座城市钦定为 X 国的核心城市,这 \(k\) 座城市需满足以下两个条件:
- 这 \(k\) 座城市可以通过道路,在不经过其他城市的情况下两两相互到达。
- 定义某个非核心城市与这 \(k\) 座核心城市的距离为,这座城市与 \(k\) 座核心城市的距离的最小值。那么所有非核心城市中,与核心城市的距离最大的城市,其与核心城市的距离最小。你需要求出这个最小值。
输入格式
第一行 \(2\) 个正整数 \(n,k\)。
接下来 \(n - 1\) 行,每行 \(2\) 个正整数 \(u,v\),表示第 \(u\) 座城市与第 \(v\) 座城市之间有一条长度为 \(1\) 的道路。
数据范围:
- \(1 \le k < n \le 10 ^ 5\)。
- \(1 \le u,v \le n, u \ne v\),保证城市与道路形成一棵树。
输出格式
一行一个整数,表示答案。
样例 #1
样例输入 #1
6 3
1 2
2 3
2 4
1 5
5 6
样例输出 #1
1
提示
【样例说明】
钦定 \(1,2,5\) 这 \(3\) 座城市为核心城市,这样 \(3,4,6\) 另外 \(3\) 座非核心城市与核心城市的距离均为 \(1\),因此答案为 \(1\)。
两次dfs求树的直径
一定要考虑 根节点 对dep[] maxdep[]的影响
根节点dep maxdep 要置为 0 但如果正常写的话 会将其赋值为0+1=1!
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,k;
struct Tree {
int nxt,from,to,val;
} edge[N<<1];
int head[N],cnt;
int root;
inline void add(int u,int v) {
cnt++;
edge[cnt].to=v;
edge[cnt].from=u;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int num,dep[N],zj,fa[N];
void dfs1(int u,int fat) {
if(u!=root)
dep[u]=dep[fat]+1;
if(dep[u]>zj) {
zj=dep[u];
num=u;
}
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
if(v==fat)continue;
// dep[v]=dep[u]+1;
dfs1(v,u);
}
}
int f[N];
void dfs2(int u,int fat) {
if(u!=root)
dep[u]=dep[fat]+1;
if(dep[u]>zj) {
zj=dep[u];
num=u;
}
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
if(v==fat)continue;
// dep[v]=dep[u]+1;
f[v]=u;
dfs2(v,u);
}
}
int maxdep[N];
int mid;
void dfs3(int u,int fat) {
if(u!=mid)
maxdep[u]=1;
for(int i=head[u]; i; i=edge[i].nxt) {
int v=edge[i].to;
if(v==fat)continue;
dfs3(v,u);
maxdep[u]=max(maxdep[u],maxdep[v]+1);
}
}
bool cmp(int x,int y) {
return x>y;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1; i<n; i++) {
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
zj=0,num=-1;
memset(dep,0,sizeof(dep));
root=1;
dfs1(1,0);
memset(dep,0,sizeof(dep));
zj=0;
root=num;
dfs2(num,0);
mid=num;
for(int i=1; i<=(zj+1)/2; i++)mid=f[mid];
dfs3(mid,0);
sort(maxdep+1,maxdep+n+1,cmp);
cout<<maxdep[k+1]<<"\n";
return 0;
}