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

 const eps=0.0001;
type node=record
po,next,len:longint;
end; var e:array[..] of node;
fa,dep,p,f,s,q,qq:array[..] of longint;
d,w,g:array[..] of double;
v:array[..] of boolean;
md,tot,n,root,i,l,u,len,x,y,z:longint;
h,r,m,ans,lim:double; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function maxx(a,b:double):double;
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].len:=z;
e[len].next:=p[x];
p[x]:=len;
end; procedure getroot(x,fa:longint); //找重心
var i,y:longint;
begin
i:=p[x];
f[x]:=;
s[x]:=;
while i<> do
begin
y:=e[i].po;
if not v[y] and (y<>fa) then
begin
getroot(y,x);
s[x]:=s[x]+s[y];
f[x]:=max(f[x],s[y]);
end;
i:=e[i].next;
end;
f[x]:=max(f[x],tot-s[x]);
if f[x]<f[root] then root:=x;
end; function calc(x:longint):boolean;
var f,r,i,y,j,h,t:longint;
begin
f:=; r:=; q[]:=x;
dep[x]:=;
fa[x]:=;
h:=; t:=;
j:=md; //这个优化使数据某个点快了十倍,md表示之前处理的子树最深的链的深度
while f<=r do
begin
x:=q[f];
g[dep[x]]:=maxx(g[dep[x]],d[x]);
while (j>=) and (j+dep[x]>=l) do //倒序入队,保证满足路径边数下界,维护单调降队列
begin
while (h<=t) and (w[j]>w[qq[t]]) do dec(t);
inc(t);
qq[t]:=j;
dec(j);
end;
while (h<=t) and (qq[h]+dep[x]>u) do inc(h); //端头出队满足上界
if (h<=t) and (w[qq[h]]+d[x]>=) then
begin
md:=max(md,dep[x]);
exit(true);
end;
if dep[x]<u then
begin
i:=p[x];
while i<> do
begin
y:=e[i].po;
if (fa[x]<>y) and not v[y] then
begin
fa[y]:=x;
dep[y]:=dep[x]+;
d[y]:=d[x]+e[i].len-m;
inc(r);
q[r]:=y;
end;
i:=e[i].next;
end;
end;
inc(f);
end;
md:=max(md,dep[x]);
for i:= to dep[x] do
w[i]:=maxx(w[i],g[i]);
exit(false);
end; function check(x:longint):boolean;
var i,y:longint;
begin
md:=;
check:=false;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
d[y]:=e[i].len-m;
if calc(y) then
begin
check:=true;
break;
end;
end;
i:=e[i].next;
end;
for i:= to md do
begin
w[i]:=-;
g[i]:=-;
end;
end; procedure work(x:longint);
var i,y:longint;
begin
v[x]:=true;
h:=ans;
r:=lim;
while r-h>eps do
begin
m:=(h+r)/;
if check(x) then
begin
ans:=m;
h:=m;
end
else r:=m;
end;
i:=p[x];
while i<> do
begin
y:=e[i].po;
if not v[y] then
begin
tot:=s[y];
root:=;
getroot(y,);
if s[y]>l then work(root);
end;
i:=e[i].next;
end;
end; begin
f[]:=;
readln(n);
readln(l,u);
for i:= to n- do
begin
readln(x,y,z);
add(x,y,z);
add(y,x,z);
if lim<z then lim:=z;
end;
for i:= to u do
begin
w[i]:=-;
g[i]:=-;
end;
root:=;
tot:=n;
getroot(,);
work(root);
writeln(ans::);
end.

bzoj1758的更多相关文章

  1. bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

    两题都是树分治. 1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调 ...

  2. 【bzoj1758】 Wc2010—重建计划

    http://www.lydsy.com/JudgeOnline/problem.php?id=1758 (题目链接) 题意 给出一棵树,每条边有边权,问选出一条长度为$[L,U]$的路径,使得路径上 ...

  3. [BZOJ1758][WC2010]重建计划(点分治+单调队列)

    点分治,对于每个分治中心,考虑求出经过它的符合长度条件的链的最大权值和. 从分治中心dfs下去取出所有链,为了防止两条链属于同一个子树,我们一个子树一个子树地处理. 用s1[i]记录目前分治中心伸下去 ...

  4. 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)

    [BZOJ1758][WC2010]重建计划(点分治,单调队列) 题面 BZOJ 洛谷 Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表 ...

  5. 【BZOJ1758】重建计划(点分治)

    题意: 给定一棵n个点的树,每条边有权值.求一条链,这条链包含的边数在L和U之间,且平均边权最大.N﹤=100000 思路:RYZ作业 二分答案再点分治,寻找是否有大于0且边数在L和U之间的链 f[i ...

  6. BZOJ1758: [Wc2010]重建计划

    题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...

  7. BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...

  8. 【bzoj1758】[Wc2010]重建计划

    Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...

  9. BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP

    题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...

随机推荐

  1. PHP中刷新输出缓冲

    http://www.cnblogs.com/mutuan/archive/2012/03/18/2404957.html PHP中刷新输出缓冲buffer是一个内存地址空间,Linux系统默认大小一 ...

  2. tomcat启动正常,404. Eclipse没有正确部署工程项目

    http://blog.csdn.net/lynn_wgr/article/details/7751228 在eclipse中新建的Dynamic Web Project.写好代码后,选择Run on ...

  3. MathType支持64位 WIN 7Office 2013(完美解决)(转载)

    经过几次尝试解决了,方法如下: 1. 安装MathType 6.8 (别的版本不知是否适用,本人安装的是该版本) 2. 将以下两个文件拷贝出来 C:\Program Files (x86)\MathT ...

  4. 使用AFNetworking进行图片上传

    转载自:http://blog.csdn.net/a645258072/article/details/51728806 项目中,我们经常会用到上传图片的功能,而目前的上传图片分为两种(我只知道两种, ...

  5. JS数值输入控制

    在html文本框录入数值时,可用如下方法进行控制判断. 整数:<input type="text" name="aaa" onkeypress=" ...

  6. android studio 自动序列化类插件

    https://github.com/mcharmas/android-parcelable-intellij-plugin

  7. c++与C# winform的消息通讯--(结构体与byte数组的使用)

    近期正在做一个蓝牙驱动的使用程序,其中有一块从c++发送数据到C#的部分,网上查了很多资料,大多都是介绍如何通过调用函数获取用户数据.并且在消息发送中,很少介绍如何发送一个结构体,并且结构体里面有 b ...

  8. 读取xml文件(可执行文件根目录debug)

    xml文件格式如下 <?xml version="1.0" encoding="utf-8" ?> <root> <appKey& ...

  9. QQ宠物吹泡泡游戏小助手 VC++6.0代码分析

    最近玩QQ宠物,他总是心情低落,让我很不爽,让他玩耍吧,还得自己点鼠标,所以想偷个懒,试试能不能编个程序让电脑帮我做这个事情. 要干这件事就得先找一个游戏开刀,刚开始我找的是弹力球游戏,不就是点鼠标么 ...

  10. 如何让U盘支持大于4G的文件

    U盘通常是FAT(*)格式,不能支持大于4G的文件.为了实现这个目的,通常可以把U盘格式化成NTFS或者exFAT,这两种文件系统都支持大于4G的文件. 一.格式化成NTFS第一步首先我们把优盘插入电 ...