菜菜推荐的“水题”虐了我一天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]最佳团体(分数规划+树形依赖背包)的更多相关文章

  1. 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

    题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...

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

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

  3. [JSOI2016]最佳团体 DFS序/树形DP

    题目 洛谷 P4322 [JSOI2016]最佳团体 Description 茜茜的舞蹈团队一共有\(N\)名候选人,这些候选人从\(1\)到\(N\)编号.方便起见,茜茜的编号是\(0\)号.每个候 ...

  4. bzoj4753[JSOI2016]最佳团体

    题意:01分数规划,但可选的数字之间存在森林形的依赖关系(可以认为0号点是个虚根,因为并不能选). 虽然有森林形的依赖关系,但还是可以套分数规划的思路,二分答案k,判断是否存在一个比值大于k的方案 即 ...

  5. Gym - 101002D:Programming Team (01分数规划+树上依赖背包)

    题意:给定一棵大小为N的点权树(si,pi),现在让你选敲好K个点,需要满足如果如果u被选了,那么fa[u]一定被选,现在要求他们的平均值(pi之和/si之和)最大. 思路:均值最大,显然需要01分数 ...

  6. BZOJ4753 JSOI2016最佳团体(分数规划+树形dp)

    看到比值先二分答案.于是转化成一个非常裸的树形背包.直接暴力背包的话复杂度就是O(n2),因为相当于在lca处枚举每个点对.这里使用一种更通用的dfs序优化树形背包写法.https://www.cnb ...

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

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

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

    BZOJ 4753 [Jsoi2016]最佳团体 | 树上背包 分数规划 又是一道卡精度卡得我头皮发麻的题-- 题面(--蜜汁改编版) YL大哥是24OI的大哥,有一天,他想要从\(N\)个候选人中选 ...

  9. 【BZOJ4753】最佳团体(分数规划,动态规划)

    [BZOJ4753]最佳团体(分数规划,动态规划) 题面 BZOJ Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一 ...

随机推荐

  1. power sequece

  2. mybatis SQL映射配置文件

    目录 标签常见属性(备忘) 参数样例 resultType.resultMap.discriminator 自动映射 动态SQL语句 罗列Mapper中最常用部分 标签常见属性(备忘) <sel ...

  3. mysql 数据库优化之执行计划(explain)简析

    数据库优化是一个比较宽泛的概念,涵盖范围较广.大的层面涉及分布式主从.分库.分表等:小的层面包括连接池使用.复杂查询与简单查询的选择及是否在应用中做数据整合等:具体到sql语句执行效率则需调整相应查询 ...

  4. hdu - 6282,2018CCPC湖南全国邀请赛G题,字符串,规律

    HDU – 6282 http://acm.hdu.edu.cn/showproblem.php?pid=6282 by Hzu_Tested 题意:给出两个字符串S和T,只由a,b,c三种字符组成( ...

  5. openstack golang sdk使用

    1. go get github.com/gophercloud/gophercloud import ( "github.com/gophercloud/gophercloud" ...

  6. python3【基础】-list&tuple

    一.list概述 list (列表)是python中最常用的数据类型之一,通过列表可以对数据实现最方便的存储,修改等操作.在python3中,list支持如下方法: Help on class lis ...

  7. Longge's problem(欧拉函数应用)

    Description Longge is good at mathematics and he likes to think about hard mathematical problems whi ...

  8. Nginx 使用札记

    nginx是什么? nginx是俄罗斯人 Igor Sysoev为俄罗斯访问量第二的Rambler.ru站点开发的一个十分轻量级的HTTP服务器.它是一个高性能的HTTP和反向代理服务器,同时也可以作 ...

  9. HDU 4489 The King’s Ups and Downs dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4489 The King's Ups and Downs Time Limit: 2000/1000 ...

  10. C语言的调查

    1.你对自己的未来有什么规划?做了哪些准备?从事跟本专业相关的工作.认真学习好书本的知识,并能很好的运用它. 2.你认为什么是学习?学习有什么用?现在学习动力如何?为什么?学习可以让自己懂得更多,完善 ...