求助,全WA
查看原帖
求助,全WA
1090444
zengyukai2012楼主2024/7/21 11:20
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n /*节点数*/, k /*要选出的节点数,定义一个节点的最短距离为到这 k 个节点的最短距离,选出 k 个节点,使得最大的最短距离最小*/;
int max_depth /*最大深度*/, max_depth_node /*最大深度的节点*/;
int f[MAXN]; // 记录每个节点的父节点(以直径的一端为根节点)
vector<int> a[MAXN];
int depth[MAXN] /*记录每个节点的深度*/, maxdepth[MAXN] /*记录每个节点到离他最远的节点的距离*/;
int max_dist[MAXN] /*记录每个节点到离他最远的节点的距离*/;
int ans /*答案*/;
/// @brief 排序比较函数
/// @param a 第一个数
/// @param b 第二个数
/// @return 如果 a > b,返回 true;否则返回 false
bool cmp(int a, int b)
{
	return a > b; // 降序排序
}
/// @brief DFS求初始点到其子节点的最远距离和最远距离的节点,顺便求出以初始点为根节点的树的直径
/// @param u 初始点
/// @param fa 父节点
/// @param depth 当前节点的深度
void getMaxDist(int u, int fa, int depth)
{
	if (depth > max_depth) // 如果当前节点的深度大于最大深度,更新最大深度和最大深度的节点
	{
		max_depth = depth;	// 更新最大深度
		max_depth_node = u; // 更新最大深度的节点
	}
	for (int v : a[u]) // 遍历当前节点的子节点
		if (v != fa)   // 跳过父节点
		{
			f[v] = u;					 // 记录子节点的父节点
			getMaxDist(v, u, depth + 1); // 递归求子节点的最远距离
		}
}
/// @brief DFS更新数组 depth 和 maxdepth
/// @param u 当前节点
/// @param fa 父节点
void update_depth_and_maxdepth(int u, int fa)
{
	maxdepth[u] = depth[u]; // 初始时,每个节点的最远距离就是它自己的深度
	for (int v : a[u])		// 遍历当前节点的子节点
		if (v != fa)		// 跳过父节点
		{
			update_depth_and_maxdepth(v, u);			 // 递归更新子节点的深度和最远距离
			maxdepth[u] = max(maxdepth[u], maxdepth[v]); // 更新当前节点的最远距离
		}
}
int main()
{
	ios::sync_with_stdio(false);
	cin >> n >> k;				// 读入节点数和要选出的节点数
	for (int i = 1; i < n; ++i) // 读入边
	{
		int u, v;		   // 读入边的两个端点
		cin >> u >> v;	   // 读入边的两个端点
		a[u].push_back(v); // 建立 u -> v 的边
		a[v].push_back(u); // 建立 v -> u 的边
	}
	getMaxDist(1, 0, 0);						   // 调用 DFS 算法求初始点到其子节点的最远距离和最远距离的节点,顺便求出以初始点为根节点的树的直径
	getMaxDist(max_depth_node, 0, 0);			   // 调用 DFS 算法求最大深度的节点到其子节点的最远距离和最远距离的节点,顺便求出以最大深度的节点为根节点的树的直径
	int mid_of_diameter = max_depth_node;		   // 假设最大深度的节点(一定是叶子节点)为直径的中点
	for (int i = 1; i <= (max_depth + 1) / 2; ++i) // 求直径的中点
		mid_of_diameter = f[mid_of_diameter];
	update_depth_and_maxdepth(mid_of_diameter, 0); // 更新数组 depth 和 maxdepth
	for (int i = 1; i <= n; ++i)				   // 遍历所有节点
		max_dist[i] = maxdepth[i] - depth[i];	   // 计算每个节点到离它最远的节点的距离
	sort(max_dist + 1, max_dist + n + 1, cmp);	   // 排序
	for (int i = k + 1; i <= n; ++i)			   // 选出 k 个节点
		ans = max(ans, max_dist[i] + 1);		   // 记录答案
	cout << ans << '\n';						   // 输出答案
	return 0;
}

悬 22 关

2024/7/21 11:20
加载中...