题目: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. h5 喜帖

    地址:http://139.196.27.185:8088/ 因为国庆结婚,需要邀请亲朋好友,网上找了些电子请帖,但大都要收费,贵的还有好几百,有的效果还不太好.于是花了些时间自己写了一个. 就是sw ...

  2. ES6中Promise对象个人理解

    Promise是ES6原生提供的一个用来传递异步消息的对象.它减少了传统ajax金字塔回调,可以将异步操作以同步操作的流程表达出来使得代码维护和可读性方面好很多. Promise的状态: 既然是用来传 ...

  3. 关于MAX()函数的一点思考

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/103 考虑如下表和sql: CREATE TABLE `ikno ...

  4. Structural Inference of Hierarchies in Networks(网络层次结构推断)

    Structural Inference of Hierarchies in Networks(网络层次结构推断) 1. 问题 层次结构是一种重要的复杂网络性质.这篇文章给出了层次结构的精确定义,给出 ...

  5. [Upper case conversion ] 每个单词的首小写字母转换为对应的大写字母

    Given a string , write a program to title case every first letter of words in string. Input:The firs ...

  6. zepto的返回顶部scrollTop的动画解决方法

    写移动端的时候,引入的zepto.js里的animate不包括scrollTop,所以返回顶部的时候,没有动画的效果.这里我使用的是setInterval的方法.代码详情如下 <!DOCTYPE ...

  7. PHP-CGI进程占用过多CPU

    一般情况下,PHP-CGI只在用户访问的时候会占用CPU资源,但是最近有同事反映,服务器上的的PHP-CGI进程占用了非常多的CPU,但是访问流量却非常少.这显然是一个不正常的现象,说有些地方存在故障 ...

  8. Python图片爬虫

    1.今天给大家介绍自己写的一个图片爬虫,说白了就是从网页自动上下载需要的图片 2.首先选取目标为:http://www.zhangzishi.cc/涨姿势这个网站如下图,我们的目标就是爬取该网站福利社 ...

  9. NIO中的易筋经

    匠心零度 转载请注明原创出处,谢谢! 前言 <易筋经>.天下武功出少林,而易筋经是少林寺的镇寺之宝.学好了易筋经就可以轻易地学好其它武功,只不过很少人学到了它的全部精髓.游坦之只是碰巧学了 ...

  10. 在QLabel上同时显示文字和图片的方法

    有两种方法. 1.打开UI文件,在界面右键单击QLabel对象,选改变多信息文本 选择图片再确定,左侧问号就是图片. 2.直接在QLabel写富文本 <html><head/> ...