到路径的距离就是到路径上的点最近的距离
首先看到最大值最小不难想到二分答案
下面的问题就是怎么判断,显然我们是不能穷举路径的
我们要找出消防路径的性质
仔细研究就会发现消防路径一定是树的直径的一段,这样必然最右
证明很简单,我们可以利用反证法解决,通过证明可以发现这个直径随便选一条就可以了
我们把树的直径拎出来,把直径上的点挂在直径下面(就相当于晾衣服一样……)
然后我们可以算出直径上每个点i的子树到i的最大距离,然后就很好处理了

 type node=record
po,dis,next:longint;
end; var q,d1,d2,p1,p2,p,f:array[..] of longint;
e:array[..] of node;
v:array[..] of boolean;
t,n,m,s,l,r,i,x,y,z,len,w:longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(len);
e[len].po:=y;
e[len].dis:=z;
e[len].next:=p[x];
p[x]:=len;
end; procedure dfs(x:longint);
var i,y:longint;
begin
v[x]:=true;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
dfs(y);
if d1[y]+e[i].dis>d1[x] then
begin
d2[x]:=d1[x];
p2[x]:=p1[x]; //p1,p2记录的是这棵子树最长次长延伸的方向
d1[x]:=d1[y]+e[i].dis;
p1[x]:=i;
end
else if d1[y]+e[i].dis>d2[x] then
begin
d2[x]:=d1[y]+e[i].dis;
p2[x]:=i;
end;
end;
i:=e[i].next;
end;
if d1[x]+d2[x]>d1[w]+d2[w] then w:=x;
end; procedure dfss(x:longint);
var i,y:longint;
begin
i:=p[x];
v[x]:=true;
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
dfss(y);
f[x]:=max(f[x],f[y]+e[i].dis);
end;
i:=e[i].next;
end;
end; procedure getl(x:longint);
begin
if p1[x]<> then getl(e[p1[x]].po);
inc(t); q[t]:=x; v[x]:=true;
end; function check(len:longint):boolean;
var l,r,w:longint;
begin
l:=;
r:=t;
w:=f[q[]];
while (l<t) and (w+d1[q[l+]]<=len) do //在满足最长距离不超过len的情况下使路径尽可能短
begin
inc(l);
w:=max(w,f[q[l]]-d1[q[l]]);
end;
w:=f[q[t]]+d1[q[t]];
while (r>l) and (w-d1[q[r-]]<=len) do
begin
dec(r);
w:=max(w,f[q[r]]+d1[q[r]]);
end;
if d1[q[r]]-d1[q[l]]<=s then exit(true)
else exit(false);
end; begin
readln(n,s);
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
end;
dfs();
fillchar(v,sizeof(v),false);
getl(w);
x:=w; i:=p2[x];
while i<> do
begin
y:=e[i].po;
inc(t); q[t]:=e[i].po; v[y]:=true;
d1[y]:=d1[x]+e[i].dis; //把直径提出来作为一条链,d1相当于到链头的距离
i:=p1[y]; x:=y;
end;
r:=d1[x];
for i:= to t do
begin
x:=q[i];
dfss(x);
l:=max(l,f[x]); //f处理的是子树最深距离
end;
if s<d1[q[t]] then
begin
while l<=r do
begin
m:=(l+r) shr ;
if check(m) then r:=m-
else l:=m+;
end;
end;
writeln(l);
end.

最新文章

  1. Timberwolves forward Kevin Garnett to retire _洛杉矶时报
  2. Window Server 2012 R2 没有照片查看器 打开图片都是画板问题怎么解决
  3. 使用reids结合wcf实现集群模式下的聊天室功能
  4. Hibernate-缓存
  5. CentOS下搭建使用gitlab 和tortoiseGit使用
  6. 【零基础学习iOS开发】【02-C语言】09-流程控制
  7. 图解:SQL Server SSIS包和job的部署攻略
  8. 洗礼灵魂,修炼python(71)--爬虫篇—【转载】xpath/lxml模块,爬虫精髓讲解
  9. 【Windows】+ windows下在某一文件夹下按“shift+鼠标右键”打开CMD窗口
  10. Storm知识点
  11. CCF关于NOIP竞赛程序提交的管理规则
  12. Java并发编程(七)深入剖析ThreadLocal
  13. Mybatis 记录
  14. 浏览器标识ua
  15. Linux命令——用户和用户组管理
  16. NSIS安装vcredist_64.exe
  17. Mybatis日期类型的关系判断
  18. Angular2.0知识架构图
  19. Educational Codeforces Round 63 D. Beautiful Array
  20. Vue.js实现数据的双向数据流

热门文章

  1. 02_线程的创建和启动_继承Thread方式
  2. java.util.Hashtable源码分析
  3. Newtonsoft.Json随手记
  4. Java知识总结--三大框架
  5. MVC文件上传-使用jQuery.FileUpload和Backload组件实现文件上传
  6. mysql更改默认存储引擎
  7. ecshop会员中心增加订单搜索功能
  8. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集
  9. 【JPA】两种不同的实现jpa的配置方法
  10. 加解密算法二:非对称加解密及RSA算法的实现