1. 程式人生 > >洛谷 P1395 會議(找樹的重心)

洛谷 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.