BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划

又是一道卡精度卡得我头皮发麻的题……

题面(……蜜汁改编版)

YL大哥是24OI的大哥,有一天,他想要从\(N\)个候选人中选\(K\)个小弟(\(N, K \le 2500\))。

想要成为大哥的小弟不是件容易事,必须要有一个举荐人才行,所以每个候选人\(i\)都有一个另一个候选人\(R_i\)作为举荐人,只有当举荐人\(R_i\)被大哥选为小弟时,候选人\(i\)才有可能被选。

每个候选人都有一个选取代价\(S_i\)和选取收益\(P_i\),请问大哥如何选取才能使单位代价的收益最大,即,使\(\frac{\sum P_i}{\sum S_i}\)最大?

题解

这道题也是个分数规划题!

二分答案\(mid\),如果有一种选取方案使得\(\frac{\sum P_i}{\sum S_i} > mid\),即存在比mid更优的答案,那么我们找到的\(\frac{\sum P_i}{\sum S_i}\)最大值一定大于\(mid\)。所以我们把\(\frac{\sum P_i}{\sum S_i}\)作为权值,跑一遍树上背包。

这种树上背包(\(n\)个点中取\(m\)个,取的点的父亲必须被取)有\(n^2\)的做法——在dfs序(前序)上dp。\(dp[i][j]\)表示dfs序中前\(i - 1\)个取\(j\)个的最大权值。

\(dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + val[seq[i]] - mid * cost[seq[i]]);\)

\(dp[i + sze[seq[i]]][j] = max(dp[i + sze[seq[i]]][j], dp[i][j]);\)

(seq[i]表示序列中的第i个,val是收益,cost是代价)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 2505, INF = 0x3f3f3f3f;
int n, m, val[N], cost[N], adj[N], nxt[N];
int seq[N], idx, sze[N];
double l, r = 10000, mid, dp[N][N]; void dfs(int u){
seq[++idx] = u, sze[u] = 1;
for(int v = adj[u]; v; v = nxt[v])
dfs(v), sze[u] += sze[v];
}
bool check(){
for(int i = 1; i <= idx + 1; i++)
for(int j = 0; j <= m; j++)
dp[i][j] = -INF;
dp[1][0] = 0;
for(int i = 1; i <= idx; i++)
for(int j = 0; j <= m; j++){
dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + val[seq[i]] - mid * cost[seq[i]]);
dp[i + sze[seq[i]]][j] = max(dp[i + sze[seq[i]]][j], dp[i][j]);
}
return dp[idx + 1][m] > -1e-9;
} int main(){ read(m), read(n);
m++;
for(int i = 1, fa; i <= n; i++){
read(cost[i]), read(val[i]), read(fa);
nxt[i] = adj[fa], adj[fa] = i;
}
dfs(0);
while(abs(r - l) > 1e-5){
mid = (l + r) / 2;
if(check()) l = mid;
else r = mid;
}
printf("%.3lf\n", (l + r) / 2); return 0;
}

BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划的更多相关文章

  1. bzoj 4753: [Jsoi2016]最佳团体【01分数规划+二分+树上背包】

    01分数规划,二分答案然后把判别式变成Σp[i]-Σs[i]*mid>=0,然后树上背包判断,设f[i][j]为在i点子树里选j个的最大收益,随便背包一下就好 最丧病的是神卡常--转移的时候要另 ...

  2. bzoj 4753 [Jsoi2016]最佳团体——0/1分数规划

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4753 0/1分数规划裸题. #include<iostream> #includ ...

  3. BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)

    题目链接 \(Description\) 每个点有费用si与价值pi,要求选一些带根的连通块,总大小为k,使得 \(\frac{∑pi}{∑si}\) 最大 \(Solution\) 01分数规划,然 ...

  4. BZOJ 4753 [Jsoi2016]最佳团体 ——01分数规划 树形DP

    要求比值最大,当然用分数规划. 二分答案,转化为选取一个最大的联通块使得它们的和大于0 然后我们直接DP. 复杂度$O(n^2\log {n})$ #include <map> #incl ...

  5. LUOGU P4322 [JSOI2016]最佳团体(0/1分数规划+树形背包)

    传送门 解题思路 一道0/1分数规划+树上背包,两个应该都挺裸的,话说我常数为何如此之大..不吸氧洛谷过不了啊. 代码 #include<iostream> #include<cst ...

  6. [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序

    分析: 化简一下我们可以发现,suma*ans=sumb,那么我们考虑二分ans,之后做树形背包上做剪枝. 时间复杂度证明,By GXZlegend O(nklogans) 附上代码: #includ ...

  7. 【BZOJ】4753: [Jsoi2016]最佳团体 01分数规划+树上背包

    [题意]n个人,每个人有价值ai和代价bi和一个依赖对象ri<i,选择 i 时 ri 也必须选择(ri=0时不依赖),求选择k个人使得Σai/Σbi最大.n<=2500,ai,bi< ...

  8. BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包)

    BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包) 标签:题解 阅读体验 BZOJ题目链接 洛谷题目链接 具体实现 看到分数和最值,考虑分数规划 我们要求的是一个\(\dfrac{ ...

  9. BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划

    BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划 Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人 ...

随机推荐

  1. opengl基础

    opengl opengl是一个由Khronos组织制定并维护的规范(Specification) .是一系列的图形软件编程接口,和gdi类似.opengl有很多封装的库最有名的GLFW库.接下来很多 ...

  2. RabbitMQ入门:远程过程调用(RPC)

    假如我们想要调用远程的一个方法或函数并等待执行结果,也就是我们通常说的远程过程调用(Remote Procedure Call).怎么办? 今天我们就用RabbitMQ来实现一个简单的RPC系统:客户 ...

  3. GearCase UI - 自己构建一套基于 Vue 的简易开源组件库

    最近 1 ~ 2 月除了开发小程序之外,还一直在继续深入的学习 Vuejs.利用零碎.闲暇的时间整合了一套基于 Vue 的 UI 组件库.命名为 GearCase UI,意为齿轮盒.现在把该项目进行开 ...

  4. 什么是mvc模式

    MVC是一个架构,或者说是一个设计模式,它就是强制性使应用程序的输入,处理和输出分开.将一个应用程序分为三个部分:Model,View,Controller. 原理图: 分析: Model 模型(完成 ...

  5. 配置Ubuntu16.04虚拟机 (用途:CTF_pwn)

    因为学习需要16.xx的虚拟机,所以把之前18.04的Ubuntu卸掉重装了一遍Ubuntu16.04, 考虑到我有备份和重装系统的爱好,故记之,以备后用. 目录: //最后更新时间:190122·1 ...

  6. yarn (npm) 切换设置镜像源

    设置镜像源 1.查看一下当前源 yarn config get registry 2.切换为淘宝源 yarn config set registry https://registry.npm.taob ...

  7. 初步认识CNN

    1.机器学习 (1)监督学习:有数据和标签 (2)非监督学习:只有数据,没有标签 (3)半监督学习:监督学习+非监督学习 (4)强化学习:从经验中总结提升 (5)遗传算法:适者生存,不适者淘汰 2.神 ...

  8. No.101_第二次团队会议

    时间的敲定 在这一次的会议中,明确了任务目标,将任务进行合理分配,并且规划了整个任务的时间节点,这对团队来说非常重要. 一.最终项目 在上一节课的时候,我们最终没有拿到学霸开发项目,最后爬虫也被选走了 ...

  9. C++:构造函数3——浅拷贝和深拷贝

    一.默认拷贝构造函数 拷贝构造函数是一种特殊的构造函数(详情见:http://www.cnblogs.com/duwenxing/p/7429777.html),如果用户在定义类时没有显式地编写拷贝构 ...

  10. ubuntu16.04+matlab r2015b VideoReader报错

    读取.mp4出错 需要安装gstreamer0.10-ffmpeg ` sudo add-apt-repository ppa:mc3man/gstffmpeg-keep sudo apt-get u ...