• bzoj2282


    到路径的距离就是到路径上的点最近的距离
    首先看到最大值最小不难想到二分答案
    下面的问题就是怎么判断,显然我们是不能穷举路径的
    我们要找出消防路径的性质
    仔细研究就会发现消防路径一定是树的直径的一段,这样必然最右
    证明很简单,我们可以利用反证法解决,通过证明可以发现这个直径随便选一条就可以了
    我们把树的直径拎出来,把直径上的点挂在直径下面(就相当于晾衣服一样……)
    然后我们可以算出直径上每个点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.
    View Code
  • 相关阅读:
    转载原型,原型链,继承
    转载闭包
    转载vue中的mixin的使用
    转载深拷贝和浅拷贝以及内存
    webapp项目架构畅想(vue3).md
    vite(or rollup) 实现 webpackChunkName
    并发编程
    Thread和Runnable
    synchronized关键字
    Callable
  • 原文地址:https://www.cnblogs.com/phile/p/4472972.html
Copyright © 2020-2023  润新知