当前位置: 首页 > news >正文

Bzoj1758: [Wc2010]重建计划

题面

传送门

Sol

题意就是给你一棵树,有边权
求边数在\([L, U]\)内的一条路径,使得边权和除以边数最大,输出这个最大值


二分答案+点分治+单调队列
二分一个答案\(mid\),把所有的边权减去这个\(mid\)就是\(check\)是否有一条边数满足要求的大于等于零的路径
\(bfs\)求出当前每个点到根的\(dis\)\(deep\),使其递增
记录下每个深度最大的\(dis\),维护这个的递减的单调队列即可

注意常数优化!!!

奉上加了一组数据后的\(TLE\)代码供参考加什么数据咯
然后博主不想改

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5);
const double EPS(1e-4);

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, L, U, first[_], cnt, mx[_], root, size[_], vis[_], tot;
int mark[_], tmp, deep[_];
double ans, dis[_], t[_];
struct Edge{
    int to, w, next;
} edge[_ << 1];
int head, tail, Q[_], deq[_];

IL void Add(RG int u, RG int v, RG int w){
    edge[cnt] = (Edge){v, w, first[u]}, first[u] = cnt++;
}

IL void GetRoot(RG int u, RG int ff){
    size[u] = 1, mx[u] = 0;
    for(RG int e = first[u]; e != -1; e = edge[e].next){
        RG int v = edge[e].to;
        if(vis[v] || v == ff) continue;
        GetRoot(v, u);
        size[u] += size[v];
        mx[u] = max(mx[u], size[v]);
    }
    mx[u] = max(mx[u], tot - size[u]);
    if(mx[u] < mx[root]) root = u;
}

IL void Bfs(RG double mid, RG int x){
    Q[head = tail = 0] = x, mark[x] = 1;
    while(head <= tail){
        RG int u = Q[head++];
        for(RG int e = first[u]; e != -1; e = edge[e].next){
            RG int v = edge[e].to, w = edge[e].w;
            if(vis[v] || mark[v]) continue;
            deep[v] = deep[u] + 1, dis[v] = dis[u] + (double)w - mid;
            Q[++tail] = v, mark[v] = 1;
        }
    }
}

IL bool Check(RG double mid, RG int u){
    RG int maxd = 0, flg = 0; t[0] = 0; 
    for(RG int e = first[u]; e != -1; e = edge[e].next){
        RG int v = edge[e].to, w = edge[e].w;
        if(vis[v]) continue;
        dis[v] = (double)w - mid, deep[v] = 1;
        Bfs(mid, v);
        for(RG int i = 0; i <= tail; ++i) mark[Q[i]] = 0;
        RG int he = 0, ta = -1, j = maxd;
        for(RG int i = 0; i <= tail; ++i){
            RG int x = Q[i];
            while(~j && j + deep[x] >= L){
                while(he <= ta && t[deq[ta]] < t[j]) --ta;
                deq[++ta] = j--;
            }
            while(he <= ta && deep[x] + deq[he] > U) ++he;
            if(he <= ta && dis[x] + t[deq[he]] >= 0){
                flg = 1;
                break;
            }
        }
        maxd = max(maxd, deep[Q[tail]]);
        if(flg) break;
        for(RG int i = 0; i <= tail; ++i){
            RG int x = Q[i];
            t[deep[x]] = max(t[deep[x]], dis[x]);
        }
    }
    for(RG int i = 0; i <= maxd; ++i) t[i] = -1e12;
    return flg;
}

IL void Calc(RG int u){
    RG double l = ans, r = tmp;
    while(r - l > EPS){
        RG double mid = (l + r) / 2;
        if(Check(mid, u)) l = mid;
        else r = mid;
    }
    ans = l;
}

IL void Solve(RG int u){
    vis[u] = 1, Calc(u);
    for(RG int e = first[u]; e != -1; e = edge[e].next){
        RG int v = edge[e].to;
        if(vis[v]) continue;
        root = 0, tot = size[v];
        if(tot <= L) continue;
        GetRoot(v, u), Solve(root);
    }
}

int main(RG int argc, RG char* argv[]){
    tot = n = Input(), L = Input(), U = Input();
    for(RG int i = 0; i <= n; ++i) first[i] = -1, t[i] = -1e12;
    for(RG int i = 1; i < n; ++i){
        RG int u = Input(), v = Input(), w = Input();
        Add(u, v, w), Add(v, u, w), tmp = max(tmp, w);
    }
    mx[0] = n + 1, GetRoot(1, 0), Solve(root);
    printf("%.3lf\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/cjoieryl/p/8470800.html

相关文章:

  • 图像编码介绍mark
  • redis集群部署及踩过的坑
  • 解决编译apache出现的问题:configure: error: APR not found . Please read the documentation
  • 找出OData service出错根源的小技巧
  • Quartz作业调度
  • Windows Server 2016-Win Ser 2016新增功能
  • JavaScript常用语句
  • 十六、lvm、磁盘故障小案例
  • 给Android应用开发者的十个建议
  • Accept-Language与多语言网站应用
  • [邻接表DFS]最长链和最大环
  • 使用for循环对 golang 中结构体数组取值进行修改时,需要注意的问题
  • C#基础 [07] 方法[上]
  • Window7下SourceInsight加载需要字体方法
  • 阿里云高性能AI服务 -- 基于Docker和EGS一键创建高性能Tensorflow分布式训练
  • (三)从jvm层面了解线程的启动和停止
  • [译] 怎样写一个基础的编译器
  • canvas 五子棋游戏
  • EOS是什么
  • es的写入过程
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Redis中的lru算法实现
  • SpingCloudBus整合RabbitMQ
  • ubuntu 下nginx安装 并支持https协议
  • 飞驰在Mesos的涡轮引擎上
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 缓存与缓冲
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 排序算法学习笔记
  • 前端面试之CSS3新特性
  • 双管齐下,VMware的容器新战略
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 中文输入法与React文本输入框的问题与解决方案
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • #预处理和函数的对比以及条件编译
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (python)数据结构---字典
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (过滤器)Filter和(监听器)listener
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (十一)手动添加用户和文件的特殊权限
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (学习日记)2024.01.19
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • (转)拼包函数及网络封包的异常处理(含代码)
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .Net mvc总结
  • .netcore如何运行环境安装到Linux服务器
  • .NET建议使用的大小写命名原则
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • @Data注解的作用
  • @property @synthesize @dynamic 及相关属性作用探究