树上路径
题目大意
给出一棵树,求出最小的
k
,使得,且在树中存在路径
数据范围
n
<=
题解
这一题显然 就是点分治。
以下是一道点分治的经典例题,可以看一下我写的
blog
:树中点对距离。
在对一棵子树计算答案的时候,算出重心并求出树中所有的点到重心的距离,计入
dis
数组,并排序, 维护两个指针计算答案即可。
但我们要注意一个细节,用来更新答案的两个点不能是同一棵子树的,所以当我们发现指针
i
,
算完后按照重心对当前子树分治下去即可。
Code(Pascal)
const
zd=20;
var
n,s,e,i,j,k,l,o,p,xd,cqy:longint;
ans,kk:int64;
bz:array[0..120000] of boolean;
bj:array[0..300000,1..3] of longint;
px:array[0..120000,1..2] of longint;
en,fa,sd,ph,qz,size:array[0..120000] of longint;
procedure qsort(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=bj[(l+r) div 2,1];
repeat
while bj[i,1]<m do inc(i);
while bj[j,1]>m do dec(j);
if i<=j then
begin
bj[0]:=bj[i];
bj[i]:=bj[j];
bj[j]:=bj[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
function min(a,b:int64):int64;
begin
if a<b then exit(a)
else exit(b);
end;
procedure qsortpx(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=px[(l+r) div 2,1];
repeat
while px[i,1]<m do inc(i);
while px[j,1]>m do dec(j);
if i<=j then
begin
px[0]:=px[i];
px[i]:=px[j];
px[j]:=px[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsortpx(l,j);
if i<r then qsortpx(i,r);
end;
function bl(o,dd:longint):longint;
var
i,r,ooo:longint;
begin
size[o]:=1;
for i:=en[o-1]+1 to en[o] do
if bz[bj[i,2]] and (ph[bj[i,2]]<>xd) then
begin
ph[bj[i,2]]:=xd;
r:=bl(bj[i,2],dd);
if r>0 then exit(r);
size[o]:=size[o]+size[bj[i,2]];
end;
if size[o]>=dd-size[o] then exit(o);
exit(0);
end;
procedure lfsb(o,cq,qy:longint);
var
i:longint;
begin
inc(cqy);
px[cqy,1]:=cq;
px[cqy,2]:=qy;
size[o]:=1;
for i:=en[o-1]+1 to en[o] do
if bz[bj[i,2]] and (ph[bj[i,2]]<>xd) then
begin
ph[bj[i,2]]:=xd;
lfsb(bj[i,2],cq+bj[i,3],qy);
size[o]:=size[o]+size[bj[i,2]];
end;
end;
procedure dg(o,p:longint);
var
i,j,k,l:longint;
begin
inc(xd);
ph[o]:=xd;
k:=bl(o,p);
cqy:=0;
bz[k]:=false;
inc(xd);
ph[k]:=xd;
for i:=en[k-1]+1 to en[k] do
if bz[bj[i,2]] then
begin
ph[bj[i,2]]:=xd;
lfsb(bj[i,2],bj[i,3],i-en[k-1]);
end;
qsortpx(1,cqy);
qz[cqy]:=0;
px[0,1]:=maxlongint div 2;
for i:=cqy-1 downto 1 do
if px[i,2]=px[i+1,2] then qz[i]:=qz[i+1]
else qz[i]:=i+1;
i:=0;
j:=cqy;
while i+1<j do
begin
inc(i);
while (px[i,1]+px[j-1,1]>=s) and (j>i+1) do dec(j);
if i>=j then break;
if px[i,1]+px[j,1]<s then continue;
if px[i,2]<>px[j,2] then ans:=min(ans,px[i,1]+px[j,1])
else ans:=min(ans,px[i,1]+px[qz[j],1]);
end;
for i:=1 to cqy do
if px[i,1]>=s then ans:=min(ans,px[i,1]);
for i:=en[k-1]+1 to en[k] do
if (size[bj[i,2]]<>1) and bz[bj[i,2]] then
dg(bj[i,2],size[bj[i,2]]);
end;
begin
readln(n,s,e);
for i:=1 to n-1 do
begin
readln(bj[i*2-1,1],bj[i*2-1,2],bj[i*2-1,3]);
bj[i*2,1]:=bj[i*2-1,2];
bj[i*2,2]:=bj[i*2-1,1];
bj[i*2,3]:=bj[i*2-1,3];
inc(en[bj[i*2,1]]);
inc(en[bj[i*2,2]]);
end;
for i:=1 to n do
en[i]:=en[i-1]+en[i];
qsort(1,2*n-2);
sd[0]:=-1;
sd[1]:=1;
ans:=e+1;
for i:=1 to n do
bz[i]:=true;
dg(1,n);
if ans>e then writeln(-1)
else writeln(ans);
end.