P5536 树的直径

【XR-3】核心城市

题目描述

X 国有 \(n\) 座城市,\(n - 1\) 条长度为 \(1\) 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。

X 国国王决定将 \(k\) 座城市钦定为 X 国的核心城市,这 \(k\) 座城市需满足以下两个条件:

  1. \(k\) 座城市可以通过道路,在不经过其他城市的情况下两两相互到达。
  2. 定义某个非核心城市与这 \(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;
}
posted @ 2023-05-02 22:10  N0zoM1z0  阅读(21)  评论(0编辑  收藏  举报