bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)
菜菜推荐的“水题”虐了我一天T T...(菜菜好强强qwq~
显然是个分数规划题,二分答案算出p[i]-mid*s[i]之后在树上跑依赖背包,选k个最大值如果>0说明还有更优解。
第一次接触树形依赖背包,所以之前写的十几发WA和TLE都是错误写法,我还是naive啊T T
树形依赖背包的普遍做法是按dfs序DP,设f[i][j]为dfs序为i的点,已经选了j个点的最大价值,nxt[i]为i的下一个子树的dfs序则有:
f[nxt[i]][j]=f[i][j]
f[i+1][j+1]=f[i][j]+w[i]
注意树形依赖背包最好使用刷表法,因为如果要求代价必须为k并且权值有负数的话使用填表法可能会导致从不合法状态转移。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=,inf=1e9;
struct poi{int too,pre;}e[maxn];
int n,k,x,tot,cnt,mx;
int dfn[maxn],nxt[maxn],last[maxn],s[maxn],p[maxn];
double f[maxn][maxn],w[maxn];
inline void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
void dfs(int x)
{
dfn[x]=cnt++;
for(int i=last[x];i;i=e[i].pre)dfs(e[i].too);
nxt[dfn[x]]=cnt;
}
int main()
{
read(k);read(n);
for(int i=;i<=n;i++)read(s[i]),read(p[i]),read(x),add(x,i),mx=max(mx,p[i]);
dfs();
double l=,r=1e4;
while(r-l>1e-)
{
double mid=(l+r)/;
for(int i=;i<=n;i++)w[dfn[i]]=1.0*p[i]-mid*s[i];
for(int i=;i<=n+;i++)for(int j=;j<=k+;j++)f[i][j]=-inf;
for(int i=;i<=n;i++)
for(int j=;j<=min(i,k+);j++)
{
if(f[i][j]>f[nxt[i]][j])f[nxt[i]][j]=f[i][j];
if(f[i][j]+w[i]>f[i+][j+])f[i+][j+]=f[i][j]+w[i];
}
if(f[n+][k+]>1e-)l=mid;else r=mid;
}
printf("%.3lf\n",l);
}
第二种做法仅能在代价为选取点数的情况下使用,直接在树上做背包,但是在对于每一个子节点做完背包之后才把子节点的size加进父节点,这样的复杂度也是O(N^2)的。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=;
double eps=1e-,inf=1e12;
struct poi{int too,pre;}e[maxn];
int n,k,x,tot,sum;
int p[maxn],s[maxn],size[maxn],last[maxn];
double f[maxn][maxn],w[maxn],g[maxn];
void read(int &k)
{
int f=;k=;char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(c<=''&&c>='')k=k*+c-'',c=getchar();
k*=f;
}
void add(int x,int y){e[++tot].too=y;e[tot].pre=last[x];last[x]=tot;}
void dfs(int x)
{
size[x]=;f[x][]=w[x];
for(int i=last[x];i;i=e[i].pre)
{
dfs(e[i].too);
for(int j=;j<=size[x]+size[e[i].too];j++)g[j]=f[x][j];
for(int j=;j<=size[x];j++)
for(int k=;k<=size[e[i].too];k++)
g[j+k]=max(g[j+k],f[x][j]+f[e[i].too][k]);
size[x]+=size[e[i].too];
for(int j=;j<=size[x];j++)f[x][j]=g[j];
}
}
int main()
{
read(k);read(n);
for(int i=;i<=n;i++)read(s[i]),read(p[i]),read(x),add(x,i);
double l=,r=1e4;
while(r-l>eps)
{
double mid=(l+r)/;
for(int i=;i<=n;i++)w[i]=1.0*p[i]-mid*s[i];
for(int i=;i<=n;i++)for(int j=;j<=k+;j++)f[i][j]=-inf;
dfs();if(f[][k+]>eps)l=mid;else r=mid;
}
printf("%.3lf\n",l);
}
bzoj4753: [Jsoi2016]最佳团体(分数规划+树形依赖背包)的更多相关文章
- 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp
题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...
- BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包)
BZOJ4753: [Jsoi2016]最佳团体(分数规划+树上背包) 标签:题解 阅读体验 BZOJ题目链接 洛谷题目链接 具体实现 看到分数和最值,考虑分数规划 我们要求的是一个\(\dfrac{ ...
- [JSOI2016]最佳团体 DFS序/树形DP
题目 洛谷 P4322 [JSOI2016]最佳团体 Description 茜茜的舞蹈团队一共有\(N\)名候选人,这些候选人从\(1\)到\(N\)编号.方便起见,茜茜的编号是\(0\)号.每个候 ...
- bzoj4753[JSOI2016]最佳团体
题意:01分数规划,但可选的数字之间存在森林形的依赖关系(可以认为0号点是个虚根,因为并不能选). 虽然有森林形的依赖关系,但还是可以套分数规划的思路,二分答案k,判断是否存在一个比值大于k的方案 即 ...
- Gym - 101002D:Programming Team (01分数规划+树上依赖背包)
题意:给定一棵大小为N的点权树(si,pi),现在让你选敲好K个点,需要满足如果如果u被选了,那么fa[u]一定被选,现在要求他们的平均值(pi之和/si之和)最大. 思路:均值最大,显然需要01分数 ...
- BZOJ4753 JSOI2016最佳团体(分数规划+树形dp)
看到比值先二分答案.于是转化成一个非常裸的树形背包.直接暴力背包的话复杂度就是O(n2),因为相当于在lca处枚举每个点对.这里使用一种更通用的dfs序优化树形背包写法.https://www.cnb ...
- BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划
BZOJ_4753_[Jsoi2016]最佳团体_树形背包+01分数规划 Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人 ...
- BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划
BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划 又是一道卡精度卡得我头皮发麻的题-- 题面(--蜜汁改编版) YL大哥是24OI的大哥,有一天,他想要从\(N\)个候选人中选 ...
- 【BZOJ4753】最佳团体(分数规划,动态规划)
[BZOJ4753]最佳团体(分数规划,动态规划) 题面 BZOJ Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一 ...
随机推荐
- 【转】lvs、nginx、haproxy转发模式优缺点总结
原文地址: https://yq.aliyun.com/ziliao/78374 一.LVS转发模式 LVS是章文嵩博士写的一个工作于四层的高可能性软件.不像后两者支持七层转发,不过也正因为其简单,所 ...
- linux源码学习-for_each_cpu
刚开始读linux源码,第一眼就看到了这个很有意思的函数族,周末好好研究一下 3.13 这个组都是宏定义for循环,分析的时候注意到cpumask_next(),它在一个文件中定义了两次,还不是重载, ...
- Blockchain For Dummies(IBM Limited Edition
Blockchain For Dummies(IBM Limited Edition)笔记 该系列内容主要介绍用于商业的区块链,有人说区块链之于贸易,犹如因特网之于信息.在商业领域区块链可以用于交易任 ...
- tomcat 最大并发连接数设置
转自: http://blog.csdn.net/qysh123/article/details/11678903 这是个很简单的问题,但是搜了一圈,发现大家都写错了.所以这里总结一下: 几乎所有的中 ...
- 基于NABCD评论作品,及改进建议
组名:杨老师粉丝群 组长:乔静玉 组员:吴奕瑶 刘佳瑞 公冶令鑫 杨磊 杨金铭 张宇 卢帝同 一.拉格朗日2018--<飞词> 1.1 NABCD分析 N(Need,需求) ...
- OOP 学习笔记汇总
1.1 引用 1.2 const关键字 1.3 动态内存分配 1.4 内联函数和重载函数函数参数缺省值 1.5 类和对象的基本概念与用法1 2.1 类和对象的基本概念2
- HDU 5862 Counting Intersections 扫描线+树状数组
题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5862 Counting Intersections Time Limit: 12000/ ...
- .net学习-扩展
uwp uwpapp-斗鱼,微信等 云和移动优先 远程桌面连接设置 teamviewer V8内核 Node.js javascript 事件循环 express框架 bootstrap NoSQL ...
- lintcode-382-三角形计数
382-三角形计数 给定一个整数数组,在该数组中,寻找三个数,分别代表三角形三条边的长度,问,可以寻找到多少组这样的三个数来组成三角形? 样例 例如,给定数组 S = {3,4,6,7},返回 3 其 ...
- DNS缓存服务器的配置步骤
yum安装bind 编辑主配置文件/etc/named.conf 修改全局配置文件段 listen-on port 53 {172.16.19.45;}; //allow-query ...