Description

JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号。方便起见,JYY的编号是0号。

每个候选人都由一位编号比他小的候选人Ri推荐。如果Ri=0则说明这个候选人是JYY自己看上的。

为了保证团队的和谐,JYY需要保证,如果招募了候选人i,那么候选人Ri"也一定需要在团队中。

当然了,JYY自己总是在团队里的。每一个候选人都有一个战斗值Pi",也有一个招募费用Si"。

JYY希望招募K个候选人(JYY自己不算),组成一个性价比最高的团队。

也就是,这K个被JYY选择的候选人的总战斗值与总招募总费用的比值最大。


Input

输入一行包含两个正整数K和N。

接下来N行,其中第i行包含3个整数Si,Pi,Ri表示候选人i的招募费用,战斗值和推荐人编号。

对于100%的数据满足1≤K≤N≤2500,0<"Si,Pi"≤10^4,0≤Ri<i

Output

输出一行一个实数,表示最佳比值。答案保留三位小数。


Sample Input

1 2

1000 1 0

1 1000 1

Sample Output

0.001


Solution

通过题目,我们要想到一下几点:

  • 要求的是比值,01分数规划。
  • 由于要求一个单独的最优解,于是二分。
  • 用背包的思想来转移DP。

二分答案 \(now\), 则其满足不等式 $$\sum_{i}{k}p_i*now>=\sum_{i}{k}s_i$$

此时每个点对于答案的贡献即为: \(p_i*now-s_i\)

于是我们便可以对答案进行转移。




定义状态: \(f[i][j]\) 表示当前到了 DFS 序为 \(i\) 的节点,已经选了 \(j\) 个成员是的最大价值.

状态转移: 由于树形依赖关系,我们每一个节点转移有两种方向:

  • \(f[i+1][j+1]\) 即选择这个点(同时之后有机会选择这个点的子树)。
  • \(f[i+siz[i]][j+1]\) 即不选择这个点以及它的子树,此时直接转移到\(siz[i]\)之后。

然后就是 DFS+二分+DP 即可。


代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2508;
const double eps=0.00001;
struct sj{
int to;
int next;
}a[maxn];
int head[maxn],size;
void add(int x,int y)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
}
int n,k,cnt;
double w[maxn],z[maxn];
int pos[maxn],siz[maxn],id[maxn]; void dfs(int x)
{
siz[x]=1; pos[x]=++cnt;id[cnt]=x;
for(int i=head[x];i;i=a[i].next)
{int tt=a[i].to;
dfs(tt); siz[x]+=siz[tt];}
}
double f[maxn][maxn];
double val[maxn];
void dp(double mid)
{
for(int i=1;i<=n;i++) val[pos[i]]=z[i]-mid*w[i];
for(int i=1;i<=n+1;i++)
for(int j=0;j<=k+1;j++) f[i][j]=-1e18;
for(int i=0;i<=n;i++)
{int mm=min(i,k+1);
for(int j=0;j<=mm;j++)
{
if (f[i][j]+val[i]>f[i+1][j+1])
f[i+1][j+1]=f[i][j]+val[i];
if (f[i][j]>f[i+siz[id[i]]][j])
f[i+siz[id[i]]][j]=f[i][j];
}
}
} int ans;
void work()
{
cin>>k>>n;
for(int i=1;i<=n;i++)
{
int fr;
scanf("%lf%lf%d",&w[i],&z[i],&fr);
add(fr,i);
}
cnt=-1;
dfs(0);
double mid,l=eps,r=9500;
while (r-l>eps)
{
mid=(l+r)/2;
dp(mid);
if (f[n+1][k+1]>=0) l=mid;
else r=mid;
}
printf("%.3lf\n",mid);
} int main()
{
work();
return 0;
}

[JSOI2016] 最佳团队 (树形DP+01分数规划)的更多相关文章

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

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

  2. [JSOI 2016] 最佳团体(树形背包+01分数规划)

    4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2003  Solved: 790[Submit][Statu ...

  3. Bzoj4753/洛谷P4432 [JSOI2016]最佳团体(0/1分数规划+树形DP)

    题面 Bzoj 洛谷 题解 这种求比值最大就是\(0/1\)分数规划的一般模型. 这里用二分法来求解最大比值,接着考虑如何\(check\),这里很明显可以想到用树形背包\(check\),但是时间复 ...

  4. BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)

    题目链接 \(Description\) 每个点有费用si与价值pi,要求选一些带根的连通块,总大小为k,使得 \(\frac{∑pi}{∑si}\) 最大 \(Solution\) 01分数规划,然 ...

  5. P1642 规划 01分数规划+树形DP

    $ \color{#0066ff}{ 题目描述 }$ 某地方有N个工厂,有N-1条路连接它们,且它们两两都可达.每个工厂都有一个产量值和一个污染值.现在工厂要进行规划,拆除其中的M个工厂,使得剩下的工 ...

  6. 【BZOJ】4753: [Jsoi2016]最佳团体 01分数规划+树上背包

    [题意]n个人,每个人有价值ai和代价bi和一个依赖对象ri<i,选择 i 时 ri 也必须选择(ri=0时不依赖),求选择k个人使得Σai/Σbi最大.n<=2500,ai,bi< ...

  7. bzoj 4753: [Jsoi2016]最佳团体【01分数规划+二分+树上背包】

    01分数规划,二分答案然后把判别式变成Σp[i]-Σs[i]*mid>=0,然后树上背包判断,设f[i][j]为在i点子树里选j个的最大收益,随便背包一下就好 最丧病的是神卡常--转移的时候要另 ...

  8. BZOJ5281: [Usaco2018 Open]Talent Show(01分数规划&DP)

    5281: [Usaco2018 Open]Talent Show Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 166  Solved: 124[S ...

  9. jzoj3454 表白(love)解题报告(01分数规划+DP)

    题目链接:https://jzoj.net/senior/#contest/show/2414/2 题目描述: 鸡腿是CZYZ的著名DS,但是不想追妹子的DS不是好GFS,所以鸡腿想通过表白来达到他追 ...

随机推荐

  1. cv2.minAreaRect() 生成最小外接矩形

    简介   使用python opencv返回点集cnt的最小外接矩形,所用函数为 cv2.minAreaRect(cnt) ,cnt是所要求最小外接矩形的点集数组或向量,这个点集不定个数.   cv2 ...

  2. VMware vSphere6.0 服务器虚拟化部署安装图解

    一 VMware vSphere部署的前期规划要点 1 vSphere的优点 (略) 2 如何利用现在的设备架构虚拟化环境 在虚拟化过程中,用户大多会考虑目前现有的服务器.存储.交换机等基础设备是否可 ...

  3. 《毛毛虫团队》第八次团队作业:ALPHA冲刺

    一:实验名称:软件测试与ALPHA冲刺 二:实验目的与要求 (1)掌握软件测试基础技术. (2)学习迭代式增量软件开发过程(Scrum). 三:实验步骤 任务一:各个成员今日完成的任务: 任务二:明日 ...

  4. python学习笔记-环境安装【1】

    1.在 WINDOWS 下面要运行命令 pip install virtualenvwrapper-win才行 参考地址http://blog.csdn.net/liuhongyue/article/ ...

  5. python报错UnicodeDecodeError:

    Python 里面的编码和解码也就是 unicode 和 str 这两种形式的相互转化.编码是 unicode -> str,相反的,解码就 是 str -> unicode.剩下的问题就 ...

  6. 基于matlab的蓝色车牌定位与识别---定位

    接着昨天的工作继续.定位的过程有些是基于车牌的颜色进行定位的,自己则根据数字图像一些形态学的方法进行定位的. 合着代码进行相关讲解. 1.相对彩色图像进行灰度化,然后对图像进行开运算.再用小波变换获取 ...

  7. 扫雷游戏 NOIP(入门)

    题目描述: 扫雷游戏是一款十分经典的单机小游戏.它的精髓在于,通过已翻开格子所提示的周围格地雷数,来判断未翻开格子里是否是地雷. 现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格的周围格地雷 ...

  8. iPhone如何设置自定义铃声?无需连接电脑,轻松几步就搞定!

    转载自: https://baijiahao.baidu.com/s?id=1594988016778457969&wfr=spider&for=pc 受够了iPhone自带的千篇一律 ...

  9. 《linux设备驱动开发详解》笔记——18 ARM linux设备树

    18.1 设备树的起源 linux 2.6及之前,大量板级信息被硬编码到内核里,十分庞大,大量冗余代码: linux 2.6之前,引入了设备树: 设备树源于OpenFirmware,描述硬件的数据结构 ...

  10. supervisor 安装使用

     简介 Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启.它是通过fork/exec的方式把这些被管 ...