好题
显然是分数规划,二分答案之后我们要找是否存在一条边数在[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.