到路径的距离就是到路径上的点最近的距离
首先看到最大值最小不难想到二分答案
下面的问题就是怎么判断,显然我们是不能穷举路径的
我们要找出消防路径的性质
仔细研究就会发现消防路径一定是树的直径的一段,这样必然最右
证明很简单,我们可以利用反证法解决,通过证明可以发现这个直径随便选一条就可以了
我们把树的直径拎出来,把直径上的点挂在直径下面(就相当于晾衣服一样……)
然后我们可以算出直径上每个点i的子树到i的最大距离,然后就很好处理了
1 type node=record 2 po,dis,next:longint; 3 end; 4 5 var q,d1,d2,p1,p2,p,f:array[0..300010] of longint; 6 e:array[0..600010] of node; 7 v:array[0..300010] of boolean; 8 t,n,m,s,l,r,i,x,y,z,len,w:longint; 9 10 function max(a,b:longint):longint; 11 begin 12 if a>b then exit(a) else exit(b); 13 end; 14 15 procedure add(x,y,z:longint); 16 begin 17 inc(len); 18 e[len].po:=y; 19 e[len].dis:=z; 20 e[len].next:=p[x]; 21 p[x]:=len; 22 end; 23 24 procedure dfs(x:longint); 25 var i,y:longint; 26 begin 27 v[x]:=true; 28 i:=p[x]; 29 while i<>0 do 30 begin 31 y:=e[i].po; 32 if not v[y] then 33 begin 34 dfs(y); 35 if d1[y]+e[i].dis>d1[x] then 36 begin 37 d2[x]:=d1[x]; 38 p2[x]:=p1[x]; //p1,p2记录的是这棵子树最长次长延伸的方向 39 d1[x]:=d1[y]+e[i].dis; 40 p1[x]:=i; 41 end 42 else if d1[y]+e[i].dis>d2[x] then 43 begin 44 d2[x]:=d1[y]+e[i].dis; 45 p2[x]:=i; 46 end; 47 end; 48 i:=e[i].next; 49 end; 50 if d1[x]+d2[x]>d1[w]+d2[w] then w:=x; 51 end; 52 53 procedure dfss(x:longint); 54 var i,y:longint; 55 begin 56 i:=p[x]; 57 v[x]:=true; 58 while i<>0 do 59 begin 60 y:=e[i].po; 61 if not v[y] then 62 begin 63 dfss(y); 64 f[x]:=max(f[x],f[y]+e[i].dis); 65 end; 66 i:=e[i].next; 67 end; 68 end; 69 70 procedure getl(x:longint); 71 begin 72 if p1[x]<>0 then getl(e[p1[x]].po); 73 inc(t); q[t]:=x; v[x]:=true; 74 end; 75 76 function check(len:longint):boolean; 77 var l,r,w:longint; 78 begin 79 l:=1; 80 r:=t; 81 w:=f[q[1]]; 82 while (l<t) and (w+d1[q[l+1]]<=len) do //在满足最长距离不超过len的情况下使路径尽可能短 83 begin 84 inc(l); 85 w:=max(w,f[q[l]]-d1[q[l]]); 86 end; 87 w:=f[q[t]]+d1[q[t]]; 88 while (r>l) and (w-d1[q[r-1]]<=len) do 89 begin 90 dec(r); 91 w:=max(w,f[q[r]]+d1[q[r]]); 92 end; 93 if d1[q[r]]-d1[q[l]]<=s then exit(true) 94 else exit(false); 95 end; 96 97 begin 98 readln(n,s); 99 for i:=1 to n-1 do 100 begin 101 readln(x,y,z); 102 add(x,y,z); 103 add(y,x,z); 104 end; 105 dfs(1); 106 fillchar(v,sizeof(v),false); 107 getl(w); 108 x:=w; i:=p2[x]; 109 while i<>0 do 110 begin 111 y:=e[i].po; 112 inc(t); q[t]:=e[i].po; v[y]:=true; 113 d1[y]:=d1[x]+e[i].dis; //把直径提出来作为一条链,d1相当于到链头的距离 114 i:=p1[y]; x:=y; 115 end; 116 r:=d1[x]; 117 for i:=1 to t do 118 begin 119 x:=q[i]; 120 dfss(x); 121 l:=max(l,f[x]); //f处理的是子树最深距离 122 end; 123 if s<d1[q[t]] then 124 begin 125 while l<=r do 126 begin 127 m:=(l+r) shr 1; 128 if check(m) then r:=m-1 129 else l:=m+1; 130 end; 131 end; 132 writeln(l); 133 end.