洛谷 P1395 会议(找树的重心)

题目描述

有一个村庄居住着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<=1000

100%数据n<=50000

program df;
type point=^node;
node=record
date,ends:longint;
next:point;
end;
var i,j,n,m,x,y,z,k,t,root,size:longint;
path:array[0..100000] of point;
d:array[0..100000] of longint;
b:array[0..100000] of boolean;

function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;

procedure com(x,y:longint);
var i:point;
begin
i:=path[x];
new(path[x]);
path[x]^.ends:=y;
path[x]^.next:=i;
end;

procedure dfs(x:longint);
var i:point;
y,t:longint;
begin
d[x]:=0; t:=0;
b[x]:=true;
i:=path[x];
while i<>nil do
begin
y:=i^.ends;
if not b[y] then
begin
dfs(y);
d[x]:=d[x]+d[y]+1; //记录该点的子节点个数
t:=max(t,d[y]+1);
end;
i:=i^.next;
end;
t:=max(t,n-d[x]-1); //记录以该点为树根的子树中含有子节点最多的子树的节点数
if (size>t) or ((size=t) and (root>x)) then //以子节点多为保证,取编号最小(可理解为找一个可以近似把树分成两半的点为树根)
begin
size:=t;
root:=x; //记录树根
end;
end;

begin
readln(n);
for i:=1 to n-1 do
begin
readln(x,y);
com(x,y);
com(y,x);
end;
size:=10000000;
dfs(1);
fillchar(b,sizeof(b),false);
z:=0;
dfs(root);
for i:=1 to n do
z:=z+d[i];
writeln(root,’ ‘,z);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值