前置

树形 dp,二分。

题意

本质上是一个树上背包,需要选不少于 \(k\) 个物品,每个物品有一个重量 \(w\) 和价值 \(v\),求性价比最大值。

分析

既然是性价比,显然是分数规划。

先介绍一下分数规划是什么:

我们二分这个最大性价比。

假设当前枚举到 \(mid\),则我们将每个点的价值修改为

\[v-mid \times w
\]

然后我们正常做树形 dp,然后统计一下是否有价值大于等于 \(0\) 的即可。

那么为什么这样呢?

假设性价比为 \(g\),我们选的是

\[p_1,p_2,...p_s( k\le s \le n)
\]

则我们有

\[\frac {\sum_{i=1}^s{v_{p_i}}}{\sum_{i=1}^s{w_{p_i}}}=g
\]

进而可以推出

\[\sum_{i=1}^s{w_{p_i} \times g}=\sum_{i=1}^s{v_{p_i}}
\]

那么,当我们定义价值 \(val_i=v_i-w_i \times g\) 时,有

\[\sum_{i=1}^s{val_{p_i}}=0\ge0
\]

成立,故以上算法正确。

实现

比较好说,先二分出来 \(g\),然后跑树形背包即可,注意要一边计算大小 \(size_p\) 一边跑背包,不然复杂度 \(O(n^3)\),加上二分可能 TLE。(虽然我没试过)

然后就是注意把精度卡到 \(0.0001\),不然会 WA。

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 110;
typedef double db; int ver[N * 2], nxt[N * 2], hd[N], idx; inline void add (int x, int y) {
ver[++idx] = y;
nxt[idx] = hd[x];
hd[x] = idx;
} int n, w[N], v[N], k, s[N];
bool mk[N];
db dp[N][N], g[N]; void dfs (int u, int fa) {
dp[u][0] = 0; dp[u][1] = g[u]; s[u] = 1;
for (int i = hd[u]; i ;i = nxt[i]) {
int y = ver[i];
if (y == fa) continue;
dfs(y, u);
s[u] += s[y]; //注意size和dp要一起算
for (int j = min(n, s[u]);j >= 1;j--) { //处理背包
for (int z = 0;z <= min(j - 1, s[y]);z++) {
dp[u][j] = max(dp[u][j], dp[u][j - z] + dp[y][z]);
}
}
}
} bool check (db x) {
for (int i = 1;i <= n;i++) g[i] = v[i] - x * w[i]; //处理val
for (int i = 1;i <= n;i++) for (int j = 0;j <= n;j++) dp[i][j] = -200000;
dfs(1, 0);
db res = -1;
for (int i = 1;i <= n;i++) for (int j = k;j <= n;j++) {
res = max(res, dp[i][j]);
}
if (res >= 0) return 1;
return 0;
} int main () {
cin >> n >> k;
for (int i = 1;i <= n;i++) cin >> v[i];
for (int i = 1;i <= n;i++) cin >> w[i];
for (int i = 1;i < n;i++) {
int x, y;
cin >> x >> y;
add(x, y); add(y, x);
}
db l = 0, r = 200000; //二分
while (r - l > 0.0001) { //注意精度
db mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid - 0.0001;
}
printf("%.2lf", l);
return 0;
}

P3874 砍树 题解的更多相关文章

  1. [7.18NOIP模拟测试5]砍树 题解(数论分块)

    题面(加密) 又考没学的姿势……不带这么玩的…… 考场上打了个模拟 骗到30分滚粗了 稍加思考(滑稽)可将题面转化为: 求一个最大的$d$,使得 $\sum \limits _{i=1}^n {(\l ...

  2. 7. 18 test 砍树题解

    (题面保密,内部人员可览) 首先观察题面,可得出如下公式 ∑(ceil(a[i] /d)*d−a[i])≤k 其中,ceil(a[i] /d)表示在需要被砍伐之前所经过的轮数,ceil函数是为了保证一 ...

  3. 7.18 NOIP模拟测试5 星际旅行+砍树+超级树

    T1 星际旅行 题意:n个点,m条边,无重边,有自环,要求经过m-2条边两次,2条边一次,问共有多少种本质不同的方案.本质不同:当且仅当至少存在一条边经过次数不同. 题解:考试的时候理解错题,以为他是 ...

  4. AC日记——砍树 codevs 1388

    1388 砍树  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Description 伐木工人米尔科需要砍倒M米长的木 ...

  5. 1369 xth 砍树

    1369 xth 砍树  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 在一个凉爽的夏夜,xth 和 ...

  6. [CSP-S模拟测试]:砍树(数学+模拟)

    题目传送门(内部题1) 输入格式 第一行两个整数$n$,$k$,代表树苗的数量和最大看书的总长度.第二行n个整数$a_i$,代表林先森希望每棵树苗的最终高度. 输出格式 一行一个整数,代表最大可能的d ...

  7. noip模拟8[星际旅行·砍树·超级树·求和]

    也不能算考得好,虽然这次A了一道题,但主要是那道题太简单了,没啥成就感,而且有好多人都A掉了 除了那一道,其他的加起来一共拿了25pts,这我能咋办,无奈的去改题 整场考试的状态并不是很好啊,不知道是 ...

  8. NOIP模拟测试5「星际旅行·砍树·超级树」

    星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...

  9. codevs 1388 砍树

    时间限制: 1 s  空间限制: 256000 KB  题目等级 : 黄金 Gold 题目描述 Description 伐木工人米尔科需要砍倒M米长的木材.这是一个对米尔科来说很容易的工作,因为他有一 ...

  10. Vijos1448校门外的树 题解

    Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...

随机推荐

  1. Python随机UserAgent库,让你不再手动敲UA!

    前言 之前也懵懵懂懂写过python爬虫,但是经常被网站的反爬机制干趴下,然后手动写了个随机UA库,情况才好些.今天在互联网畅游时发现,有一个能够产生随机UA的第三方库! 安装第三方库 老生常谈啦,p ...

  2. MySQL的sql语句执行流程(简述)

    导言: MySQL和服务器端对接的时候,我们知道一般就是服务器端会打包一些SQL命令去增删改查数据库,这个打包的数据库SQL语句数据包一般为4MB,再大一些就不会被数据库端接收了 但是我们可以自己更改 ...

  3. Java关键字break、continue 、return的区别,嵌套循环,数组的概念以及数组案例

    一.关键字 break.continue .return的区别 1.break : 用于在switch..case中放置语句块穿透, ​ 用于跳出循环 // 从1-100 遇到7的倍数 break f ...

  4. LeetCode 周赛 348(2023/06/05)数位 DP 模板学会了吗

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 加入知识星球提问! 往期回顾:LeetCode 单周赛第 347 场 · 二维空间上的 LIS 最长递增子序列问题 ...

  5. tar 命令压缩时报错 Removing leading `/' from member names 解决方法

    原文:https://www.cnblogs.com/operationhome/p/9802554.html 在使用tar命令进行压缩打包的时候我们常常会遇到下面的错误.虽然它不会影响我们最后的压缩 ...

  6. R 包初学者指南

    由于微信不允许外部链接,你需要点击文章尾部左下角的 "阅读原文",才能访问文中链接. 基于 11 个最常见的用户问题介绍 R 软件包. R 包是由社区开发 (developed b ...

  7. CANoe_ Trace 和 Graphics 窗口的介绍和使用

    Canoe是一款用于汽车网络分析和仿真的工具,其中包括Trace和Graphics两个窗口,用于显示和分析CAN网络数据.以下是对Canoe的Trace和Graphics窗口的简要介绍和使用说明: 1 ...

  8. 尚医通day09-【用户平台搭建详细步骤】(内附源码)

    页面预览 首页 医院详情 第01章-服务器端渲染和客户端渲染 1.搜索引擎优化 1.1.什么是搜索引擎优化 SEO 是网站为了获得更多的流量,对网站的结构及内容进行调整和优化,以便搜索引擎 (百度,g ...

  9. JUC同步锁原理源码解析二--ReentrantReadWriteLock

    JUC同步锁原理源码解析二----ReentrantReadWriteLock 1.读写锁的来源 ​ 在开发场景下,对于写操作我们为了保证原子性所以需要上锁,但是对于读操作,由于其不改变数据,只是单纯 ...

  10. Elasticsearch 6.x 配置search-guard 插件

    前言   es之前版本一直无用户验证功能,不过官方有提供一x-pack,但是问题是付费.在es的6.3.2版本中,已经集成了x-pack,虽然es团队已经对x-pack开源,但是在该版本中如果需要使用 ...