题目: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分数规划+点分治+单调队列)的更多相关文章

  1. BZOJ 1758: [Wc2010]重建计划 01分数规划+点分治+单调队列

    code: #include <bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in", ...

  2. [WC2010]重建计划(分数规划+点分治+单调队列)

    题目大意:给定一棵树,求一条长度在L到R的一条路径,使得边权的平均值最大. 题解 树上路径最优化问题,不难想到点分治. 如果没有长度限制,我们可以套上01分数规划的模型,让所有边权减去mid,求一条路 ...

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

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

  4. 【BZOJ 1758】【WC 2010】重建计划 分数规划+点分治+单调队列

    一开始看到$\frac{\sum_{}}{\sum_{}}$就想到了01分数规划但最终还是看了题解 二分完后的点分治,只需要维护一个由之前处理过的子树得出的$tb数组$,然后根据遍历每个当前的子树上的 ...

  5. [WC2010][BZOJ1758]重建计划-[二分+分数规划+点分治]

    Description 传送门 Solution 看到那个式子,显然想到分数规划...(不然好难呢) 然后二分答案,则每条边的权值设为g(e)-ans.最后要让路径长度在[L,U]范围内的路径权值&g ...

  6. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

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

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

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

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

  9. BZOJ1758: [Wc2010]重建计划

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

随机推荐

  1. OC学习6——面相对象的三大特性

    我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这也是面向对象的三大特征.OC学习篇之---类的三大特性(封装,继承,多态) 1.封装(Encapsulation)是指将对象的状态信息 ...

  2. JS画几何图形之二【圆】

    半径为r的圆上的点p(x,y)与圆心O(x0,y0)的关系: x = x0+rcosA;  y = y0+rsinA ,A为弧度 样例:http://www.zhaojz.com.cn/demo/dr ...

  3. Redis分布式集群搭建

    Redis集群架构图 上图蓝色为redis集群的节点. 节点之间通过ping命令来测试连接是否正常,节点之间没有主区分,连接到任何一个节点进行操作时,都可能会转发到其他节点. 1.Redis的容错机制 ...

  4. SharedPreferences 存List集合,模拟数据库,随时存取

    PS:SharedPreferences只要稍微学过一点就会用,他本身通过创建一个Editor对象,来存储提交,而editor可以存的格式为 他里面可以存一个Set<String> Set ...

  5. C#常用单词

    C#语言需要的一些英语注释 About -----关于 abstract -----抽象的 Abstract ------抽象的 Accept -----接受 activat -----活跃 add  ...

  6. RabbitMQ教程(一) ——win7下安装RabbitMQ

    RabbitMQ依赖erlang,所以先安装erlang,然后再安装RabbitMQ; 下载RabbitMQ,下载地址: rabbitmq-server-3.5.6.exe和erlang,下载地址:o ...

  7. Django学习日记06_视图_URLconf、View

    URLconf Django通过URLconf来响应网页请求,在项目设置settings.py中,设定了ROOT_URLCONF值来指定默认的URLconf(即mysite.urls),当HTTPRe ...

  8. [转]Linux网络配置命令ifconfig输出信息解析

    eth0      Link encap:Ethernet  HWaddr 00:1e:4f:e9:c2:84 inet addr:128.224.163.153  Bcast:128.224.163 ...

  9. TurnipBit开发板“趣味赛”:平衡力大比拼

    让孩子在快乐自由的游戏中培养编程思维 平衡力大挑战是我们经常经常玩的的一个小游戏,脑补画面的话比较常见的是单腿平衡力大比拼,摇晃幅度小者胜利.游戏好玩归好玩,但是想要公平判断胜负却不容易.下面就教大家 ...

  10. J2EE 项目 org.apache.jasper.JasperException: 解决方法

    项目从一个电脑转移到另一台电脑总是有各种意外qaq~ 刚放假把从实验室的项目拷回自己的电脑回家继续coding,结果出了这个错误.... 各个地方都调试原来是Tomcat版本问题!!!我电脑上的是6. ...