BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划
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]最佳团体 | 树上背包 分数规划的更多相关文章
- bzoj 4753: [Jsoi2016]最佳团体【01分数规划+二分+树上背包】
01分数规划,二分答案然后把判别式变成Σp[i]-Σs[i]*mid>=0,然后树上背包判断,设f[i][j]为在i点子树里选j个的最大收益,随便背包一下就好 最丧病的是神卡常--转移的时候要另 ...
- bzoj 4753 [Jsoi2016]最佳团体——0/1分数规划
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4753 0/1分数规划裸题. #include<iostream> #includ ...
- BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)
题目链接 \(Description\) 每个点有费用si与价值pi,要求选一些带根的连通块,总大小为k,使得 \(\frac{∑pi}{∑si}\) 最大 \(Solution\) 01分数规划,然 ...
- BZOJ 4753 [Jsoi2016]最佳团体 ——01分数规划 树形DP
要求比值最大,当然用分数规划. 二分答案,转化为选取一个最大的联通块使得它们的和大于0 然后我们直接DP. 复杂度$O(n^2\log {n})$ #include <map> #incl ...
- LUOGU P4322 [JSOI2016]最佳团体(0/1分数规划+树形背包)
传送门 解题思路 一道0/1分数规划+树上背包,两个应该都挺裸的,话说我常数为何如此之大..不吸氧洛谷过不了啊. 代码 #include<iostream> #include<cst ...
- [Jsoi2016]最佳团体 BZOJ4753 01分数规划+树形背包/dfs序
分析: 化简一下我们可以发现,suma*ans=sumb,那么我们考虑二分ans,之后做树形背包上做剪枝. 时间复杂度证明,By GXZlegend O(nklogans) 附上代码: #includ ...
- 【BZOJ】4753: [Jsoi2016]最佳团体 01分数规划+树上背包
[题意]n个人,每个人有价值ai和代价bi和一个依赖对象ri<i,选择 i 时 ri 也必须选择(ri=0时不依赖),求选择k个人使得Σai/Σbi最大.n<=2500,ai,bi< ...
- BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包)
BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包) 标签:题解 阅读体验 BZOJ题目链接 洛谷题目链接 具体实现 看到分数和最值,考虑分数规划 我们要求的是一个\(\dfrac{ ...
- BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划
BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划 Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人 ...
随机推荐
- Java线程wait和sleep的区别
Java中调用wait方法或者sleep方法都可以让线程进入waitint或者time-waiting状态,但是它们还是 有所不同的: wait是Object中的方法,而sleep则是Thread中的 ...
- 004 --Mysql中的锁的问题
死锁 死锁是指两个或多个事务在同一个资源上相互占用, 并请求锁定对方占用的资源, 从而导致恶性循环的现象. 当多个事务试图以不同顺序锁定资源时, 就可能产生死锁.死锁发生以后, 只有部分或者完全回滚其 ...
- Spring学习(4)IOC容器配置bean:定义与实例化
一. IOC容器配置 1. 一些概念 (1)IOC容器: 定义:具有管理对象和管理对象之间的依赖关系的容器. 作用:应用程序无需自己创建对象,对象由IOC容器创建并组装.BeanFactory是IO ...
- Netty源码分析第3章(客户端接入流程)---->第4节: NioSocketChannel注册到selector
Netty源码分析第三章: 客户端接入流程 第四节: NioSocketChannel注册到selector 我们回到最初的NioMessageUnsafe的read()方法: public void ...
- k8s环境搭建--基于kubeadm方法
环境 master node: 数量 1, 系统 ubuntu 16.04_amd64 worker node: 数量 1, 系统 ubuntu 16.04_amd64 kubernetes 版本: ...
- 高可用OpenStack(Queen版)集群-6.Nova控制节点集群
参考文档: Install-guide:https://docs.openstack.org/install-guide/ OpenStack High Availability Guide:http ...
- last命令详解
基础命令学习目录首页 原文链接:https://blog.csdn.net/jerry_1126/article/details/54427119 [root@xiaoma /root] test!# ...
- LeetCode 566. Reshape the Matrix (C++)
题目: In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a n ...
- 【Alpha】阶段第十次Scrum Meeting
[Alpha]阶段第十次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 登出接口 编写后端说明文档 赵智源 编写脚本实现测试的持续集成 前测试点页面跳转逻辑测试 ...
- YQCB冲刺周第七天
站立会议 任务看板 燃尽图 今天的任务为实现个人设置中的修改密码.设置金额的功能.以及界面的美化. 遇到的问题为修改自己密码时获得当前用户的id问题.