BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758
01分数规划,所以我们对每个重心进行二分。于是问题转化为Σw[e]-mid>=0, 对于一棵子树维护点的dep,dis,并用队列q存下来。令mx[i]表示当前dep为i的最大权值,维护一个单调队列dq,维护当前符合条件的mx,当我们从q的队尾向前扫时,它的dep是递减的,利用这个性质维护单调队列,最后更新一遍mx。具体看代码吧TAT
代码:
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#include<set>
#include<cmath>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 209000
#define inf int(1e9)
#define mm 1000000007
#define esp 1e-6
using namespace std;
#define ll long long
struct data{int obj,pre; double c;
}e[maxn*2];
int head[maxn],s[maxn],q[maxn],dq[maxn],dep[maxn],fa[maxn],vis[maxn];
double ans,lim,dis[maxn],mx[maxn];
int n,m,tot,sum,mn,rt,L,U;
int read(){
int x=0,f=1; char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
void insert(int x,int y,double z){
e[++tot].obj=y; e[tot].c=z; e[tot].pre=head[x]; head[x]=tot;
}
void dfs(int u,int fa){
s[u]=1; int mx=0;
for (int j=head[u];j;j=e[j].pre){
int v=e[j].obj;
if (v!=fa&&!vis[v]) {
dfs(v,u);
s[u]+=s[v];
mx=max(mx,s[v]);
}
}
mx=max(mx,sum-mx);
if (mx<mn) mn=mx,rt=u;
}
bool go(int u,double mid){
int up=0;
for (int j=head[u];j;j=e[j].pre){
int v=e[j].obj;
if (vis[v]) continue;
dep[v]=1; dis[v]=e[j].c-mid; fa[v]=u;
int l=0,r=1; q[1]=v;
while (l<r){
int now=q[++l];
for (int k=head[now];k;k=e[k].pre){
int v=e[k].obj;
if (v!=fa[now]&&!vis[v]){
fa[v]=now; dep[v]=dep[now]+1; dis[v]=dis[now]+e[k].c-mid;
q[++r]=v;
}
}
}
int tail=r; l=1; r=0; int now=up;
rep(i,1,tail){
while (dep[q[i]]+now>=L&&now>=0){
while (l<=r&&mx[now]>mx[dq[r]]) r--;
dq[++r]=now;
now--;
}
while (l<=r&&dep[q[i]]+dq[l]>U) l++;
if (l<=r&&dis[q[i]]+mx[dq[l]]>=0) return 1;
}
rep(i,up+1,dep[q[tail]]) mx[i]=-inf;
rep(i,1,tail) {
int now=dep[q[i]];
mx[now]=max(mx[now],dis[q[i]]);
}
up=max(up,dep[q[tail]]);
}
return 0;
}
void jud(int u){
double l=ans,r=lim;
while (r-l>=0.0001){
double mid=(l+r)/2;
if (go(u,mid)) l=mid;
else r=mid;
}
ans=l;
}
void solve(int u){
mn=inf;
dfs(u,0);
u=rt;
jud(u);
vis[u]=1;
for (int j=head[u];j;j=e[j].pre){
int v=e[j].obj;
if (!vis[v]) {
sum=s[v];
if (sum>L) solve(v);
}
}
}
int main(){
n=read();
L=read(); U=read();
int x,y; double z;
rep(i,1,n-1){
x=read(); y=read(); scanf("%lf",&z);
insert(x,y,z);
insert(y,x,z);
lim=max(lim,z);
}
sum=n;
solve(1);
printf("%.3lf\n",ans);
return 0;
}
BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)的更多相关文章
- BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列
code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...
- [WC2010]重建计划(分数规划+点分治+单调队列)
题目大意:给定一棵树,求一条长度在L到R的一条路径,使得边权的平均值最大. 题解 树上路径最优化问题,不难想到点分治. 如果没有长度限制,我们可以套上01分数规划的模型,让所有边权减去mid,求一条路 ...
- bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check
[Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4345 Solved: 1054[Submit][Status][Disc ...
- 【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列
一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的 ...
- [WC2010][BZOJ1758]重建计划-[二分+分数规划+点分治]
Description 传送门 Solution 看到那个式子,显然想到分数规划...(不然好难呢) 然后二分答案,则每条边的权值设为g(e)-ans.最后要让路径长度在[L,U]范围内的路径权值&g ...
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- BZOJ1758 WC2010 重建计划 二分答案、点分治、单调队列
传送门 看到平均数最大,自然地想到二分答案.那么我们的$check$函数就是要求:是否存在一条长度在$[L,U]$的路径,满足其权值和$\geq 0$. 看到长度在$[L,U]$,自然地想到点分治求解 ...
- 2019.01.21 bzoj1758: [Wc2010]重建计划(01分数规划+长链剖分+线段树)
传送门 长链剖分好题. 题意简述:给一棵树,问边数在[L,R][L,R][L,R]之间的路径权值和与边数之比的最大值. 思路: 用脚指头想都知道要01分数规划. 考虑怎么checkcheckcheck ...
- BZOJ1758: [Wc2010]重建计划
题解: 这题我居然做了一星期?... 平均值的极值其实也可以算是一种分数规划,只不过分母上b[i]=1 然后我们就可以二分这个值.类似与 HNOI最小圈 如果没有 链的长度的限制的话,我们直接两遍df ...
随机推荐
- C++ 知识点总结复习
C++ 1.C++是静态类型语言,使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查. 2.面向对象程序设计 C++ 完全支持面向对象的程序设计,包括面向对象开发的四大特性: 封 ...
- Python学习(三):迭代器、生成器、装饰器、递归、算法、正则
1.迭代器 迭代器是访问集合的一种方式,迭代对象从集合的第一个元素开始访问,直到元素被访问结束,迭代器只能往前不能后退,最大的优点是不要求事先准备好整个迭代过程中的元素,这个特点使得它特别适合用于遍历 ...
- Linq To EF
l简单查询:var result = from c in Entities.Customer select c; l条件查询: 普通linq写法: var result = from c in Ent ...
- Socket相关概念
lsocket的英文原义是“孔”或“插座”.作为进程通信机制,取后一种意思.通常也称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄.(其实就是两个程序通信用的.) lsocket非常类似于电 ...
- 点击盒子选中里面的单选框,并给盒子添加相应样式,美化单选框、复选框样式css用法,响应式滴
pc效果图: 移动端效果图: 代码直接上: <!DOCTYPE html> <html> <head> <meta http-equiv="Cont ...
- C# 控件拖动
https://zhidao.baidu.com/question/2116834779399609987.html [DllImport("user32.dll", EntryP ...
- 设置状态栏(UIStatusBar)样式
方法1:找到项目里面的info.plist文件,添加属性Status bar style,设置属性值为transparent black style 状态条为白色 ,设置属性值为 gray style ...
- JavaScript 计算指定月份有多少天
用 js 画工作日历的时候,需要用 js 计算指定月份一共有多少天 在网上找了些方法,都比较繁琐,后来灵机一动,想到一个偷懒的办法,分享一下 一.原理分析 要想得到某月有多少天,只需要获取到当月最后一 ...
- ASP.NET Core学习之四 在CentOS上部署.net core
一.安装CentOs 以前在大学学过linux,但是对命令行总是有一种深深的排斥感,几年之后,还是又回来了. 1.下载 现在没法FQ,就算是FQ网速也是蜗牛一样慢,我使用阿里云的镜像站进行下载速度还是 ...
- Looping over the databases on a server
SP_MSFOREACHDB 获得所有实例下数据库名称 EXEC sp_MSForEachDB 'PRINT "?"' sp_MSforeachtable USE MAST ...