题目
自从省队NOI赛前集训在scz举行之后,一个名叫cs1.6.exe的文件开始在机房广泛使用起来。每天大家都要找神犇小X借移动硬盘,考里面的这个文件。
由于机房里需要考这个文件的人太多了,每天都要花一段时间一个人一个人的去拷贝。小T觉得这实在是太麻烦了,就想找一个一劳永逸的方法。
小T调查了一下,机房有n台机器,且有局域网,所有机器通过一些网线连接起来,其整个布局是一个树形结构,即任意两台机器间都有且仅有一条路径。小T想在其中某一台机器上储存这个文件,需要的同学就可以直接通过局域网来下载这个文件。
网络上信息传输是需要时间的,我们定义两台机器间数据传输的时间为连接这两台机器的路径所包含的网线数量。虽然机房里通过局域网传个文件是很快的,但文件传输越快越好。所以小T要选择一台机器存储文件,使得所有机器下载这个文件需要的总时间(即最后一台机器完成下载的时间)尽可能短。
现在,你需要给出这个最短时间,以便让小T看看他的决策是否最优。
【数据范围】
对于30%的数据,n≤100;
对于50%的数据,n≤1000;
对于100%的数据,2≤n≤100000。
8 3
1 2
1 3
3 4
3 5
4 6
5 7
7 8
题解
由于给出的整个布局是一个树形结构,所以可以用求树上最长链的方法求
可以证明从任意一个点出发,一直走到最远的一个点,这个最远点一定是树上最长链的一端。记录端点,再从改端点出发一直走到最远的一个点,经过的路径即为树上最长链
最后结果应为树上最长链的长度+1 div 2
其中两次找最远点都可用同一个过程,注意记录上次走到的点
因为最多是每个点遍历一次,所以
时间复杂度O(n)
代码
var
n,i,j,max,ans:longint;
a:array[1..200000,1..2]of longint;
ls,next:array[1..200000]of longint;
procedure dfs(k,s,c:longint);
var
j:longint;
begin
j:=ls[k];
if max<s then
begin
max:=s;
ans:=k;
end;
while j>0 do
begin
if a[j,2]<>c then
dfs(a[j,2],s+1,k);
j:=next[j];
end;
end;
begin
assign(input,'selc.in');
assign(output,'selc.out');
reset(input);rewrite(output);
readln(n);
for i:=1 to n-1 do
begin
inc(j);
readln(a[j,1],a[j,2]);
next[j]:=ls[a[j,1]];
ls[a[j,1]]:=j;
inc(j);
a[j,1]:=a[j-1,2];
a[j,2]:=a[j-1,1];
next[j]:=ls[a[j,1]];
ls[a[j,1]]:=j;
end;
dfs(1,0,0);
max:=0;
dfs(ans,0,0);
writeln((max+1) div 2);
close(input);close(output);
end.