http://www.lydsy.com/JudgeOnline/problem.php?id=1758 (题目链接)

题意

  给出一棵树,每条边有边权,问选出一条长度为$[L,U]$的路径,使得路径上的边权平均数最大是多少。

Solution

  哈哈,爸爸终于过啦。

  首先二分答案,然后路径统计显然点分治,统计答案的时候单调队列维护一下滑动窗口里面的最值。因为要点分治若干次,我们不妨将重心预处理出来,减少常数。

  一定要小心,在点分治处理子树的时候,一定要按照深度从小到大的顺序处理,不然直接被新加的那组扫把型的数据卡掉T_T。

细节

  清空cnt。

代码

// bzoj1758
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define LD long double
#define eps 1e-4
#define inf (1ll<<60)
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std; const int maxn=100010;
int n,m,U,L,cnt,head[maxn];
struct edge {int to,next,w;}e[maxn<<1];
struct data {
int num,D;
friend bool operator < (data a,data b) {return a.D>b.D;}
}; namespace NodeDivide {
int Dargen,rt,D,maxD,sum,size[maxn],vis[maxn],Sum[maxn],f[maxn],q[maxn],h[maxn];
edge t[maxn];
double ans,deep[maxn],dis[maxn],Dis[maxn];
void link(int u,int v) {t[++cnt]=(edge){v,h[u]};h[u]=cnt;}
void dfs(int x,int fa) {
size[x]=f[x]=1;
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
dfs(e[i].to,x);
f[x]=max(f[x],size[e[i].to]);
size[x]+=size[e[i].to];
}
f[x]=max(f[x],sum-size[x]);
if (f[x]<f[rt]) rt=x;
}
void caldeep(int x,int fa,int d) {
D=max(D,d);
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa && !vis[e[i].to]) {
deep[e[i].to]=deep[x]+e[i].w;
caldeep(e[i].to,x,d+1);
}
}
void caldis(int x,int fa,int d) {
dis[d]=max(dis[d],deep[x]);
for (int i=head[x];i;i=e[i].next)
if (e[i].to!=fa && !vis[e[i].to]) caldis(e[i].to,x,d+1);
}
void solve(int x,double res) {
vis[x]=1;maxD=0;
priority_queue<data> T;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
D=0;deep[e[i].to]=e[i].w;
caldeep(e[i].to,x,1);
T.push((data){e[i].to,D});
}
while (!T.empty()) {
data tmp=T.top();T.pop();
caldis(tmp.num,x,1);
int l=1,r=0,pl=maxD,pr=maxD;
for (int i=1;i<=tmp.D;i++) {
for (;pl>-1 && pl>=L-i;pl--) {
while (l<=r && Dis[q[r]]-q[r]*res<Dis[pl]-pl*res) r--;
q[++r]=pl;
}
for (;pr>-1 && pr>U-i;pr--) while (l<=r && q[l]>=pr) l++;
if (pl<pr) ans=max(ans,dis[i]-i*res+Dis[q[l]]-q[l]*res);
}
maxD=max(maxD,tmp.D);
for (int i=1;i<=tmp.D;i++) Dis[i]=max(Dis[i],dis[i]),dis[i]=0;
}
for (int i=1;i<=maxD;i++) Dis[i]=0;
for (int i=h[x];i;i=t[i].next) if (Sum[t[i].to]>=L) solve(t[i].to,res);
vis[x]=0;
}
void caldargen(int x,int fa) {
vis[x]=1;
if (fa) link(fa,x);else Dargen=x;
for (int i=head[x];i;i=e[i].next) if (!vis[e[i].to]) {
sum=size[e[i].to],rt=0;
dfs(e[i].to,x);
Sum[rt]=sum;
caldargen(rt,x);
}
vis[x]=0;
}
void Init() {
cnt=0;
sum=n;f[rt=0]=1<<30;
dfs(1,0);Sum[rt]=sum;
caldargen(rt,0);
}
double main(double res) {
ans=-inf;
solve(Dargen,res);
return ans;
}
}
using namespace NodeDivide; void link(int u,int v,int w) {
e[++cnt]=(edge){v,head[u],w};head[u]=cnt;
e[++cnt]=(edge){u,head[v],w};head[v]=cnt;
}
int main() {
scanf("%d%d%d",&n,&L,&U);
for (int u,v,w,i=1;i<n;i++) {
scanf("%d%d%d",&u,&v,&w);
link(u,v,w);
}
Init();
double l=0,r=1000000,ans;
while (l<=r) {
double mid=(l+r)/2;
if (main(mid)>=0) l=mid+eps,ans=mid;
else r=mid-eps;
}
printf("%.3lf",ans);
return 0;
}

【bzoj1758】 Wc2010—重建计划的更多相关文章

  1. BZOJ1758: [Wc2010]重建计划

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

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

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

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

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

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

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

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

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

  6. BZOJ1758 WC2010 重建计划 二分答案、点分治、单调队列

    传送门 看到平均数最大,自然地想到二分答案.那么我们的$check$函数就是要求:是否存在一条长度在$[L,U]$的路径,满足其权值和$\geq 0$. 看到长度在$[L,U]$,自然地想到点分治求解 ...

  7. 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)

    传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...

  8. 洛谷 P4292 [WC2010]重建计划 解题报告

    P4292 [WC2010]重建计划 题目描述 \(X\)国遭受了地震的重创, 导致全国的交通近乎瘫痪,重建家园的计划迫在眉睫.\(X\)国由\(N\)个城市组成, 重建小组提出,仅需建立\(N-1\ ...

  9. [WC2010]重建计划 长链剖分

    [WC2010]重建计划 LG传送门 又一道长链剖分好题. 这题写点分治的人应该比较多吧,但是我太菜了,只会长链剖分. 如果你还不会长链剖分的基本操作,可以看看我的长链剖分总结. 首先一看求平均值最大 ...

  10. bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

    [Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Disc ...

随机推荐

  1. 【Java框架型项目从入门到装逼】第十三节 用户新增功能完结篇

    这一节,我们把用户新增的功能继续做一个完善.首先,新增成功后,需要给前台返回一个信息,就是告诉浏览器,这次用户新增的操作到底是成功了呢,还是失败了呢?为此,我们需要专门引入一个结果类,里面只有两个属性 ...

  2. 使用 vi/vim 时,粘贴进新创建文件或空文件的首行内容丢失的解决方法

    只需要进入插入模式后,回车空一行或几行,再粘贴,再把上面的几个空行back回去,就不会丢失首行的内容了.

  3. [CF1025F]Disjoint Triangles[极角排序+组合计数]

    题意 平面上有 \(n\) 个点,选出六个点构成两个三角形,问有多少种构造方式使得两个三角形没有交集. \(n\leq 2000\) 分析 枚举连接两个三角形的两个顶点,同时能够将两个三角形划分在直线 ...

  4. 您需要来自XXX的权限才能对此文件夹进行更改

    解决办法: cmd命令:del/f/s/q 文件夹

  5. 最简单的XML用法

    在传递数据时,XML和JSON是最常用的数据格式,SQL Server从很早的版本就开始支持XML格式,而对于JSON格式,SQL Server从2016版本开始支持.大多数数据库系统并没有升级到SQ ...

  6. (2)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- .NetCore启动配置 和 .NetCoreWebApi

    什么是.Net Core?.Net Core是微软开发的另外一个可以跨Linux.Windows.mac等平台的.Net.Net Core相关知识看文章地步dotnet dllname.dll 运行P ...

  7. TensorFlow训练MNIST数据集(3) —— 卷积神经网络

    前面两篇随笔实现的单层神经网络 和多层神经网络, 在MNIST测试集上的正确率分别约为90%和96%.在换用多层神经网络后,正确率已有很大的提升.这次将采用卷积神经网络继续进行测试. 1.模型基本结构 ...

  8. 软件测试_测试工具_APP测试工具_对比

    以下是我自己整理的APP测试工具对比,各个工具相关并不全面.尤其关于收费一项,我只是针对自己公司的实际情况进行对比的,每个工具还有其他收费套餐可以选择,详情可进入相关官网进行查看 以下是部分官网链接: ...

  9. win10安装tensorflow-gpu

    1.安装anaconda (最好使用清华源下载) 2.打开cmd conda create -n tensorflow pip python=3.6 activate tensorflow pip i ...

  10. Istio如何使用相同的端口访问网格外服务

    1.1.背景 写这篇文章的目的是为了说明以下问题:如何使用TCP协议相同的端口访问网格外多个服务? 这是最近直播的时候有一个同学提出的,当时我没有完全明白,“访问多集群” 的意思.后来仔细思考了一下, ...