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. Siki_Unity_7-4_高自由度沙盘游戏地图生成_MineCraft_Uniblocks插件(可拓展)

    Unity 7-4 高自由度沙盘游戏地图生成 MineCraft (插件Uniblocks) 任务1&2&3&4 素材 && 课程演示 && 课 ...

  2. Spring学习(4)IOC容器配置bean:定义与实例化

    一.  IOC容器配置 1. 一些概念 (1)IOC容器: 定义:具有管理对象和管理对象之间的依赖关系的容器. 作用:应用程序无需自己创建对象,对象由IOC容器创建并组装.BeanFactory是IO ...

  3. linux后台启动程序脚本实例

    启动安装的zookeeper和kafka #!/bin/bash # start zookeeper and kafka service echo "========== Start the ...

  4. VirtualBox共享文件夹 Windows 7 (宿主机) + Ubuntu 12.04

    1 安装增强功能包1.1 运行Ubuntu并登陆,菜单“设备”->“安装增强功能包(Install Guest Additions)”ubun1.2 桌面上会多出一个光盘图标,光盘默认自动加载到 ...

  5. mongodb基本使用(三)

    MongoDB 创建数据库 语法 MongoDB 创建数据库的语法格式如下: use DATABASE_NAME 如果数据库不存在,则创建数据库,否则切换到指定数据库. 如果你想查看所有数据库,可以使 ...

  6. TeamWork#3,Week5,The First Meeting of Our Team

    sixsix第一次会议记录 [会议时间]2014年10月23日星期四19:00-20:00 [会议形式]小组讨论 [会议地点]5号公寓 [会议主持]高雅智 [会议记录]张志浩 会议整体流程 一.签到 ...

  7. POJ 2441 Arrange the Bulls 状压dp

    题目链接: http://poj.org/problem?id=2441 Arrange the Bulls Time Limit: 4000MSMemory Limit: 65536K 问题描述 F ...

  8. Keil C51与Keil ARM共存

    转自:http://blog.chinaunix.net/uid-20734916-id-3988537.html Keil和MDK共存,按照以下步骤:1 先安装 Keil C51,安装目录改为:&q ...

  9. 全选练习-原生版和jQuery

    今天来做一些练习,做全选练习 原生版的实现: <!DOCTYPE html> <html> <head> <meta charset="UTF-8& ...

  10. 开放地址法散列表ADT

    数据结构定义如下: typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl ...