【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列
一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解
二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的结点的深度来确定$tb数组$中的滑块。
因为分数规划要找的是$max$,BFS遍历当前结点的深度越来越大,这样滑块也是单调向右滑动,所以滑块里的最大值就应当用单调队列解决
#include<cstdio>
#include<algorithm>
#define read(x) x=getint()
#define N 100003
#define eps 0.0001
#define max(a,b) (a)>(b)?a:b
using namespace std;
inline int getint() {
char c; int fh = 1, k = 0;
for( ; c < '0' || c > '9'; c = getchar()) if ( c == '-') fh = -1;
for( ; c >= '0' && c <= '9'; c = getchar()) k = k * 10 + c - '0';
return k * fh;
}
struct node {
int nxt, to, w;
} E[N << 1];
bool vis[N];
double ans = 0.0, limi = 0.0, dis[N], tb[N];
int sz[N], n, cnt = 0, L, U, point[N], root, rtm = N, fa[N], q[N], dq[N], deep[N];
inline void ins( int x, int y, int z) {++cnt; E[cnt].nxt = point[x]; E[cnt].to = y; E[cnt].w = z; point[x] = cnt;}
inline void fdrt( int x, int fa, int s) {
sz[x] = 1;
int ma = 0;
for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
if ( !vis[E[tmp].to] && E[tmp].to != fa) {
fdrt( E[tmp].to, x, s);
sz[x] += sz[E[tmp].to];
ma = max( ma, sz[E[tmp].to]);
}
ma = max( ma, s - ma);
if ( ma < rtm) {
rtm = ma;
root = x;
}
}
inline bool can( int x, double M) {
int le = 0, head, tail, h, t, now;
for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
if ( !vis[E[tmp].to]) {
head = 0;
tail = 1;
q[0] = E[tmp].to;
fa[E[tmp].to] = x;
deep[E[tmp].to] = 1;
dis[E[tmp].to] = (double) E[tmp].w - M;
while ( head != tail) {
now = q[head];
++head; if ( head >= N) head %= N;
for( int i = point[now]; i; i = E[i].nxt)
if ( !vis[E[i].to] && E[i].to != fa[now]) {
q[tail] = E[i].to;
fa[E[i].to] = now;
deep[E[i].to] = deep[now] + 1;
dis[E[i].to] = dis[now] + (double) E[i].w - M;
++tail; if ( tail >= N) tail %= N;
}
}
h = 1;
t = 0;
now = le;
for( int i = 0; i < tail; ++i) {
while ( deep[q[i]] + now >= L && now >= 0) {
while ( h <= t && tb[dq[t]] < tb[now])
--t;
dq[++t] = now;
--now;
}
while ( h <= t && deep[q[i]] + dq[h] > U)
++h;
if ( h <= t && dis[q[i]] + tb[dq[h]] >= 0)
return 1;
}
for( int i = le + 1; i <= deep[q[tail-1]]; ++i)
tb[i] = -1E9;
for( int i = 0; i < tail; ++i)
tb[deep[q[i]]] = max( tb[deep[q[i]]], dis[q[i]]);
le = max( le, deep[q[tail-1]]);
}
return 0;
}
inline void work( int x) {
double left = ans, right = limi, mid;
while ( right - left > eps) {
mid = ( left + right) / 2;
if ( can ( x, mid))
left = mid;
else
right = mid;
}
ans = left;
}
inline void dfs( int x, int s) {
vis[x] = 1;
work( x);
for( int tmp = point[x]; tmp; tmp = E[tmp].nxt)
if ( !vis[E[tmp].to]) {
rtm = N;
int ss = sz[E[tmp].to] < sz[x] ? sz[E[tmp].to] : s - sz[x];
fdrt( E[tmp].to, -1, ss);
if ( sz[E[tmp].to] > L)
dfs( root, ss);
}
}
int main() {
read(n); read(L); read(U);
int a, b, c;
for( int i = 1; i < n; ++i) {
read(a); read(b); read(c);
ins( a, b, c);
ins( b, a, c);
limi = max( limi, c);
}
fdrt( 1, -1, n);
dfs( 1, n);
printf( "%.3lf\n", ans);
return 0;
}
这样就可以了
【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列的更多相关文章
- BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)
题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...
- bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check
[Wc2010]重建计划 Time Limit: 40 Sec Memory Limit: 162 MBSubmit: 4345 Solved: 1054[Submit][Status][Disc ...
- [WC2010]重建计划(分数规划+点分治+单调队列)
题目大意:给定一棵树,求一条长度在L到R的一条路径,使得边权的平均值最大. 题解 树上路径最优化问题,不难想到点分治. 如果没有长度限制,我们可以套上01分数规划的模型,让所有边权减去mid,求一条路 ...
- BZOJ1758: [Wc2010]重建计划(01分数规划+点分治+单调队列)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1758 01分数规划,所以我们对每个重心进行二分.于是问题转化为Σw[e]-mid>=0, ...
- BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列
code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- [WC 2010]重建计划
Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案, ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- [WC2010][BZOJ1758]重建计划-[二分+分数规划+点分治]
Description 传送门 Solution 看到那个式子,显然想到分数规划...(不然好难呢) 然后二分答案,则每条边的权值设为g(e)-ans.最后要让路径长度在[L,U]范围内的路径权值&g ...
随机推荐
- SSH----MVC框架模式与分层架构
MVC框架模式 MVC框架模式是web开发中一种软件设计典范,他的全名是(Model -View -Controller),是模型(model)--视图(view)--控制器(controller)的 ...
- 第5章 绘图基础_5.1-5.4 GDI绘图
5.1 GDI的原理和结构 (1)提供一种特殊机制彻底隔离应用程序与不同输出设备(eg.显示器或打印机),以便支持 与设备无关的图形. 光栅设备(如显示器.激光打印机):图像是由点构成的矩阵 图形输出 ...
- Java 序列化Serializable
a)当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口: b)当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化: c) static,trans ...
- u3d_Shader_effects笔记5 第二章 通过UV,进行纹理移动
1.前面心情 公司最近打包,像我等小弟闲着,看代码容易困,没事偷着学shader,不过还是要多交流才行. 2.本文参考 这次参考比较多:由texture uv延伸问题多,主要是不明白变量定义: htt ...
- 如何用patch打补丁
patch -p1 < *.patch -p1代表忽略第一层目录(patch文件中的).
- Zygote进程【2】——Zygote的分裂
在Zygote的诞生一文中init进程是如何一步步创建Zygote进程的,也了解了Zygote的进程的作用.Zygote进程的诞生对于整个Java世界可以说有着"开天辟地"的作用, ...
- 关于maya动力学系统的一些总结
maya动力学有以下几套系统: 1.刚体.柔体系统 刚体系统的典型节点连接方法如下: 物体的变换节点.形状节点连接rigidBody节点,刚体节点输出力到解算器节点,解算器输出新的变换到变换节点 值得 ...
- Oracle之多行记录变一行记录,行变列,并排序(wmsys.wm_concat)
原帖:http://www.cnblogs.com/nayitian/p/3231734.html wmsys.wm_concat Definition: The Oracle PL/SQL WM_C ...
- C# 断点续传原理与实现
在了解HTTP断点续传的原理之前,让我们先来了解一下HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种.请求协议是由 客户机(浏览器)向服务器(WEB SERVER)提交请求时发 ...
- SQL Server DB Type and CLR Type
这段时间学习SQL Server CLR编程,但是SQL CLR编程,里面所使用的数据类型为CLE TYPE,它多少与 Db TYPE有些区别,在网上找到一个列表http://geekswithblo ...