题目描述
有一个村庄居住着 n 个村民,有 n−1 条路径使得这 n 个村民的家联通,每条路径的长度都为 1。现在村长希望在某个村民家中召开一场会议,村长希望所有村民到会议地点的距离之和最小,那么村长应该要把会议地点设置在哪个村民的家中,并且这个距离总和最小是多少?若有多个节点都满足条件,则选择节点编号最小的那个点。
输入格式
第一行,一个数 n,表示有 n 个村民。
接下来 n−1 行,每行两个数字 a 和 b,表示村民 a 的家和村民 b 的家之间存在一条路径。
输出格式
一行输出两个数字 x 和 y。
x 表示村长将会在哪个村民家中举办会议。
y 表示距离之和的最小值。
输入输出样例
输入 #1
4 1 2 2 3 3 4输出 #1
2 4说明/提示
数据范围
对于 70% 数据 n≤1e3。
对于 100 数据 n≤5e4。
板题 ,所以直接上代码了
下面代码可以直接当板子使用 (:
ps:求 所有点到重心距离的和 也可以用bfs得到答案
AC代码如下:
//树的最小重心点+所有点到重心距离的和
//链式前向星板
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 1;
int n, ans, a, b, sum, d[maxn], dis[maxn];
int inf = 1e9;
vector<int> g[maxn];
queue<int> q;
bool vis[maxn];
void dfs(int s, int f)
{
d[s] = 1;
int res = 0;
for (int i = 0; i < g[s].size(); i++)
{
if (g[s][i] == f)//跑到直接的父亲
continue;
dfs(g[s][i], s);
d[s] += d[g[s][i]];
res = max(res, d[g[s][i]]);
}
res = max(res, n - d[s]);
if (res < inf || (res == inf && ans > s))
{
inf = res;
ans = s;
}
}
int main()
{
ios::sync_with_stdio(0);
cin >> n;
for (int i = 0; i < n - 1; i++)
{
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs(1, 0);
q.push(ans);
while (!q.empty())
{
int e = q.front();
q.pop();
vis[e] = true;
sum += dis[e];
for (int i = 0; i < g[e].size(); i++)
{
if (!vis[g[e][i]])
{
q.push(g[e][i]);
dis[g[e][i]] = dis[e] + 1;
}
}
}
printf("%d %d", ans, sum);
return 0;
}