• bzoj1758


    好题
    显然是分数规划,二分答案之后我们要找是否存在一条边数在[l,u]长度和为正的路径
    可以用树的分治来解决这个问题
    我们假设当前处理的是过点root的路径
    显然我们不好像之前男人八题里先算出所有答案,然后再剔除不合法的
    这里我们的统计方法是依次处理每个子树,算这个子树中的从根到某个节点的路径和之前处理的子树的路径能产生的最大值
    这样就能保证路径过root且不重不漏
    然后不难想到维护w[s]表示处理到当前子树前边数为s的路径长度和的最大值,处理完当前子树更新w[]
    考虑能产生的最大合法路径我们bfs当前子树,由于从子树根到节点的边数是逐渐增加的
    不难想到维护一个单调队列来解决,具体维护见程序
    由于这道题时限比较紧,如果我们先二分然后用树分治判定是否合法,非常耗时
    思考一下我们的流程,我们找到树的重心后要处理过重心的路径
    我们完全可以在这时内二分得出过重心的最优值然后向下分治时,这个最优值就成了以后的下界
    这样不断提高下界可以快不少
    还有一些优化细节见程序

      1 const eps=0.0001;
      2 type node=record
      3        po,next,len:longint;
      4      end;
      5 
      6 var e:array[0..200010] of node;
      7     fa,dep,p,f,s,q,qq:array[0..100010] of longint;
      8     d,w,g:array[0..100010] of double;
      9     v:array[0..100010] of boolean;
     10     md,tot,n,root,i,l,u,len,x,y,z:longint;
     11     h,r,m,ans,lim:double;
     12 
     13 function max(a,b:longint):longint;
     14   begin
     15     if a>b then exit(a) else exit(b);
     16   end;
     17 
     18 function maxx(a,b:double):double;
     19   begin
     20     if a>b then exit(a) else exit(b);
     21   end;
     22 
     23 procedure add(x,y,z:longint);
     24   begin
     25     inc(len);
     26     e[len].po:=y;
     27     e[len].len:=z;
     28     e[len].next:=p[x];
     29     p[x]:=len;
     30   end;
     31 
     32 procedure getroot(x,fa:longint);  //找重心
     33   var i,y:longint;
     34   begin
     35     i:=p[x];
     36     f[x]:=0;
     37     s[x]:=1;
     38     while i<>0 do
     39     begin
     40       y:=e[i].po;
     41       if not v[y] and (y<>fa) then
     42       begin
     43         getroot(y,x);
     44         s[x]:=s[x]+s[y];
     45         f[x]:=max(f[x],s[y]);
     46       end;
     47       i:=e[i].next;
     48     end;
     49     f[x]:=max(f[x],tot-s[x]);
     50     if f[x]<f[root] then root:=x;
     51   end;
     52 
     53 function calc(x:longint):boolean;
     54   var f,r,i,y,j,h,t:longint;
     55   begin
     56     f:=1;  r:=1;    q[1]:=x;
     57     dep[x]:=1;
     58     fa[x]:=0;
     59     h:=1; t:=0;
     60     j:=md;  //这个优化使数据某个点快了十倍,md表示之前处理的子树最深的链的深度
     61     while f<=r do
     62     begin
     63       x:=q[f];
     64       g[dep[x]]:=maxx(g[dep[x]],d[x]);
     65       while (j>=0) and (j+dep[x]>=l) do  //倒序入队,保证满足路径边数下界,维护单调降队列
     66       begin
     67         while (h<=t) and (w[j]>w[qq[t]]) do dec(t);
     68         inc(t);
     69         qq[t]:=j;
     70         dec(j);
     71       end;
     72       while (h<=t) and (qq[h]+dep[x]>u) do inc(h);  //端头出队满足上界
     73       if (h<=t) and (w[qq[h]]+d[x]>=0) then
     74       begin
     75         md:=max(md,dep[x]);
     76         exit(true);
     77       end;
     78       if dep[x]<u then
     79       begin
     80         i:=p[x];
     81         while i<>0 do
     82         begin
     83           y:=e[i].po;
     84           if (fa[x]<>y) and not v[y] then
     85           begin
     86             fa[y]:=x;
     87             dep[y]:=dep[x]+1;
     88             d[y]:=d[x]+e[i].len-m;
     89             inc(r);
     90             q[r]:=y;
     91           end;
     92           i:=e[i].next;
     93         end;
     94       end;
     95       inc(f);
     96     end;
     97     md:=max(md,dep[x]);
     98     for i:=1 to dep[x] do
     99       w[i]:=maxx(w[i],g[i]);
    100     exit(false);
    101   end;
    102 
    103 function check(x:longint):boolean;
    104   var i,y:longint;
    105   begin
    106     md:=1;
    107     check:=false;
    108     i:=p[x];
    109     while i<>0 do
    110     begin
    111       y:=e[i].po;
    112       if not v[y] then
    113       begin
    114         d[y]:=e[i].len-m;
    115         if calc(y) then
    116         begin
    117           check:=true;
    118           break;
    119         end;
    120       end;
    121       i:=e[i].next;
    122     end;
    123     for i:=1 to md do
    124     begin
    125       w[i]:=-1000000007;
    126       g[i]:=-1000000007;
    127     end;
    128   end;
    129 
    130 procedure work(x:longint);
    131   var i,y:longint;
    132   begin
    133     v[x]:=true;
    134     h:=ans;
    135     r:=lim;
    136     while r-h>eps do
    137     begin
    138       m:=(h+r)/2;
    139       if check(x) then
    140       begin
    141         ans:=m;
    142         h:=m;
    143       end
    144       else r:=m;
    145     end;
    146     i:=p[x];
    147     while i<>0 do
    148     begin
    149       y:=e[i].po;
    150       if not v[y] then
    151       begin
    152         tot:=s[y];
    153         root:=0;
    154         getroot(y,0);
    155         if s[y]>l then work(root);
    156       end;
    157       i:=e[i].next;
    158     end;
    159   end;
    160 
    161 begin
    162   f[0]:=2147483647;
    163   readln(n);
    164   readln(l,u);
    165   for i:=1 to n-1 do
    166   begin
    167     readln(x,y,z);
    168     add(x,y,z);
    169     add(y,x,z);
    170     if lim<z then lim:=z;
    171   end;
    172   for i:=1 to u do
    173   begin
    174     w[i]:=-1000000007;
    175     g[i]:=-1000000007;
    176   end;
    177   root:=0;
    178   tot:=n;
    179   getroot(1,0);
    180   work(root);
    181   writeln(ans:0:3);
    182 end.
    View Code
  • 相关阅读:
    2020-01月-02月
    Work needing Technologies
    gcc和 gdb工具(转)
    pyenv and grunt-contrib-testem
    Statistics Books
    HTML5学习--SVG全攻略(基础篇)
    一个完整的学院网站实现过程
    JavaScript 常用单词整理
    一张图教会CSS3倒影
    Python大数据处理案例
  • 原文地址:https://www.cnblogs.com/phile/p/4472986.html
Copyright © 2020-2023  润新知