菜菜推荐的“水题”虐了我一天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. QT在子窗口外单击关闭子窗口

    网上查到了好多种方法,1.添加过滤器(eventFilter),2.重写鼠标单击事件,这两种方法都要判断鼠标单击位置是不是在子窗口上.而且在可编辑控件上如(下拉框.文本编辑框等),父窗口会直接传递到可 ...

  2. Scala基础知识笔记2

    1 类 1.1 定义一个简单的类 1.2 field的getter 和 setter方法 感觉成员变量定义成  var 属性名=属性值即可,  不需要定义成 val 或者 private就行, // ...

  3. hbase和ZooKeeper集群安装配置

    一:ZooKeeper集群安装配置 1:解压zookeeper-3.3.2.tar.gz并重命名为zookeeper. 2:进入~/zookeeper/conf目录: 拷贝zoo_sample.cfg ...

  4. RyuBook1.0案例一:Switching Hub项目源码分析

    开发目标 实现一个带MAC地址学习功能的二层交换机 Openflow交换机与Openflow控制器安全通道建立步骤 switch and controller建立未加密TCP连接或者加密的TLS连接 ...

  5. 【Pthon入门学习】多级菜单小例子

    menu_list = { '北京':{ '昌平':{ '回龙观':{ '和谐家园':{}, '矩阵小区':{}, '北店家园':{} }, '沙河':{ '北街家园1区':{}, '北街家园2区': ...

  6. hashlib模块使用详情

    python常用模块目录 一:hashlib简介 1.什么叫hash:hash是一种算法(不同的hash算法只是复杂度不一样)(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224 ...

  7. RIGHT-BICEP单元测试——“二柱子四则运算升级版”

    RIGHT-BICEP单元测试 ——“二柱子四则运算升级版” ”单元测试“这对于我们来说是一个全新的专业含义,在上了软件工程这门课,并当堂编写了简单的"求一组数中的最大值"函数的单 ...

  8. vs中如何使用NuGet

    在vs中如何打开NuGet? 1.工具→NuGet程序包管理器→程序包管理控制台 2.没有的话,就去  工具→扩展和更新   搜索nuget 如果你点击工具,没看到Nuget这些字样,请注意汉化名字为 ...

  9. Linux的压缩/解压缩文件处理 zip & unzip

    Linux的压缩/解压缩命令详解及实例 压缩服务器上当前目录的内容为xxx.zip文件 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip filename.zip 另:有些服 ...

  10. C语言 aabbcc、abc、fabc、aabc

    输入一个字符串,匹配字符串中连续出现的字符串.并且连续个数相等 如输入 aabbcc.abc.fabc.aabc.aabbc 分别输出yes还是no #include<stdio.h>#i ...