bzoj 4753 最佳团体

Written with StackEdit.

Description

\(JSOI\)信息学代表队一共有N名候选人,这些候选人从\(1\)到\(N\)编号。方便起见,\(JYY\)的编号是\(0\)号。每个候选人都由一位编号比他小的候选人\(R_i\)推荐。如果\(R_i=0\)则说明这个候选人是\(JYY\)自己看上的。为了保证团队的和谐,\(JYY\)需要保证,如果招募了候选人\(i\),那么候选人\(R_i\)"也一定需要在团队中。当然了,\(JYY\)自己总是在团队里的。每一个候选人都有一个战斗值P\(_i\)",也有一个招募费用\(S_i\)"。\(JYY\)希望招募\(K\)个候选人(\(JYY\)自己不算),组成一个性价比最高的团队。也就是,这\(K\)个被\(JYY\)选择的候选人的总战斗值与总招募总费用的比值最大。

Input

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

接下来\(N\)行,其中第\(i\)行包含\(3\)个整数\(S_i,P_i,R_i\)表示候选人i的招募费用,战斗值和推荐人编号。

对于\(100\%\)的数据满足\(1≤K≤N≤2500,0<S_i,P_i≤10^4,0≤R_i<i.\)

Output

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

Sample Input

1 2

1000 1 0

1 1000 1

Sample Output

0.001

Solution

  • \(0/1\)分数规划与树形背包的结合.
  • 目标是最大化\(\sum a_i/\sum b_i\).
  • 考虑二分答案\(x\),若该答案合法,则\(\sum a_i/\sum b_i\geq x\).
  • 移项,有\(\sum a_i-x\cdot \sum b_i\geq 0\).
  • 令每个物品的权值为\(a_i-x\cdot b_i\),则转化为一般的最大化总权值的树形背包.得出最大总权值后,若其非负,则说明\(x\)合法,否则不合法.
#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
typedef long long LoveLive;
const double eps=1e-5;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>‘9‘||jp<‘0‘)&&jp!=‘-‘)
        jp=getchar();
    if (jp==‘-‘)
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>=‘0‘&&jp<=‘9‘)
        {
            out=out*10+jp-‘0‘;
            jp=getchar();
        }
    return out*fh;
}
const int MAXN=2510;
int a[MAXN],b[MAXN],Fa[MAXN];//p,s,r
int cnt=0,head[MAXN],to[MAXN<<1],nx[MAXN<<1];
double w[MAXN],f[MAXN][MAXN];
int sons[MAXN],siz[MAXN];
inline void add(int u,int v)
{
    ++cnt;
    to[cnt]=v;
    nx[cnt]=head[u];
    head[u]=cnt;
}
int n,k;
void dfs(int u)
{
    siz[u]=1;
    f[u][0]=0;
    if(sons[u]==0)
        {
            f[u][1]=w[u];
            return;
        }
    for(int i=head[u];i;i=nx[i])
        {
            int v=to[i];
            dfs(v);
            int lim=min(k,siz[u]);
            for(int j=lim;j>=0;--j)
                {
                    for(int p=0;p<=siz[v];++p)
                        {
                            if(j+p>k)
                                break;
                            f[u][j+p]=max(f[u][j+p],f[u][j]+f[v][p]);
                        }
                }
            siz[u]+=siz[v];
        }
    for(int i=k;i>=0;--i)
        {
            if(i>=1)
                f[u][i]=f[u][i-1]+w[u];
            else
                f[u][i]=0;
        }
}
int check(double x)
{
    for(int i=1;i<=n;++i)
        w[i]=1.0*a[i]-1.0*b[i]*x;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            f[i][j]=-inf;
    dfs(1);
    if(f[1][k]>-eps)
        return 1;
    return 0;
}
int main()
{
    k=read(),n=read();
    ++n,++k;
    for(int i=2;i<=n;++i)
        {
            b[i]=read();
            a[i]=read();
            Fa[i]=read();
            ++Fa[i];
            ++sons[Fa[i]];
            add(Fa[i],i);
        }
    double L=0,R=1e4,ans=0;
    while(R-L>eps)
        {
            double mid=(L+R)/2;
            if(check(mid))
                {
                    ans=mid;
                    L=mid;
                }
            else
                R=mid;
        }
    printf("%.3f\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/jklover/p/10025778.html

时间: 2024-10-09 07:27:47

bzoj 4753 最佳团体的相关文章

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

题目链接 \(Description\) 每个点有费用si与价值pi,要求选一些带根的连通块,总大小为k,使得 \(\frac{∑pi}{∑si}\) 最大 \(Solution\) 01分数规划,然后dp,设f[i][j]表示i子树选j个的最大权值和,直接暴力背包转移即可 在枚举子节点选的数量时,假设x有1.2.3.4四个子节点,复杂度为 \(1*sz[1]+sz[1]*sz[2]+(sz[1]+sz[2])*sz[3]+(sz[1]+sz[2]+sz[3])*sz[4]\) 相当于每对点在L

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

题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了保证团队的和谐,JYY需要保证,如果招募了候选人i,那么候选人Ri"也一定需要在团队中.当然了,JYY自己总是在团队里的.每一个候选人都有一个战斗值Pi",也有一个招募费用Si".JYY希望招募K个候选人(JYY自己不算),组成一个性价比最高的团队.也就是,这K个被JYY选择的候

BZOJ4753: [Jsoi2016]最佳团体

Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 844  Solved: 318[Submit][Status][Discuss] Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位 编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了保证团队的和谐,JYY需要保证, 如果招募了候选人i,那么候选人Ri"也一定需要在团队中.当然了,JYY

bzoj4753 最佳团体

题目描述 JSOI 信息学代表队一共有 NN 名候选人,这些候选人从 11 到 NN 编号.方便起见,JYY 的编号是 00 号.每个候选人都由一位编号比他小的候选人R_iRi? 推荐.如果 R_i = 0Ri?=0?,则说明这个候选人是 JYY 自己看上的. 为了保证团队的和谐,JYY 需要保证,如果招募了候选人 ii,那么候选人 R_iRi? 也一定需要在团队中.当然了,JYY 自己总是在团队里的.每一个候选人都有一个战斗值 P_iPi? ,也有一个招募费用 S_iSi? .JYY 希望招募

P4322 [JSOI2016]最佳团体

01分数规划+树形dp,其实很好想,题也不难. 题干: 题目描述 JSOI 信息学代表队一共有 NNN 名候选人,这些候选人从 111 到 NNN 编号.方便起见,JYY 的编号是 000 号.每个候选人都由一位编号比他小的候选人RiR_iRi? 推荐.如果 Ri=0R_i = 0Ri?=0?,则说明这个候选人是 JYY 自己看上的. 为了保证团队的和谐,JYY 需要保证,如果招募了候选人 iii,那么候选人 RiR_iRi? 也一定需要在团队中.当然了,JYY 自己总是在团队里的.每一个候选人

BZOJ 4753 二分+树形DP

思路: 先二分答案 f[x][j]表示在x的子树里选j个点 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]); 初始化 x!=0 -> f[x][1]=p[x]-s[x]*mid x=0 -> f[x][0]=0 类似4033的那样转移 看似O(n^3)实际O(n^2) 加一个二分 复杂度O(能过) //By SiriusRen #include <cstdio> #include <cstring> #include <al

【2018.10.1】【JSOI2016】最佳团体(bzoj4751)

一看到“比值”最大(性价比最高)就知道跟分数规划有关系了.(这里讲过分数规划) 然后看到 要选一个候选人 必须选他的前置,画画图就知道是一棵树. 所以这道题是二分比值,然后判断在树上能否得到这个答案. 那怎么判断? 这篇的T1讲过,典型的树上背包,像那道T1一样在树上暴力转移即可.其实这题的父子依赖性质跟那道T1差不多,因为连通块就是一片父子的依赖关系(当然最上边的根节点的祖先是还没处理到的). 那树上每个点都要遍历一下它的所有儿子,对于每个儿子还要枚举以这个儿子为根的子树中选出的点. 原文地址

[JSOI2016]最佳团体

嘟嘟嘟 01分数规划+树形背包. 然后就没了. 结果我调了半天,原因还是树形背包不熟练. 我是用dfs序求的,转化的时候,是dp[i][j]转化到dp[i + 1][j + 1]或dp[i +siz[pos[i]]][j],而不是像普通的dp从别的状态转化到dp[i][j],所以最后的答案应该考虑到dp[n + 1][m + 1],而不是只到n,而且初始化的时候也要到n + 1这一层.这也就是我为啥总WA第3个点. 1 #include<cstdio> 2 #include<iostre

#2071. 「JSOI2016」最佳团体

\(01\)分数规划不能直接套板子了,窝一开始想着用什么简单的方法缩点(每个点只有一个入度啊)然后跑拓扑图求解(保存每个点的最优值,通过牛顿迭代减少运算次数),问题是这样还要考虑人数,可不可做都不知道.转念一想,既然每个点只有一个入度,那么环从\(0\)号点\(jyy(orz)\)开始是肯定无法到达的(无法从任何一个点进入环).题目没说不可行就一定是可行的(雾),直接从\(0\)号点遍历即可,自然而然的拓扑图且还有个容易操作的性质,任意两条路不会汇合,理由如上,路只能分散,这不就是颗树吗?实现的