bzoj 4753 最佳团体 —— 01分数规划+树形背包

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4753

注意赋初值为 -inf;

eps 设为 1e-3 会 WA ...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=2505;
int n,m,hd[xn],ct,to[xn],nxt[xn],s[xn],w[xn],siz[xn];
double ans,f[xn][xn],eps=1e-5,a[xn];
void add(int x,int y){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct;}
int rd()
{
    int ret=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
    while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return f?ret:-ret;
}
void dfs(int x)
{
    f[x][1]=a[x]; siz[x]=1;
    for(int i=hd[x],u;i;i=nxt[i])
    {
        dfs(u=to[i]);
        for(int j=min(m,siz[x]+siz[u]);j>=1;j--)
            for(int k=max(1,j-siz[x]);k<j&&k<=siz[u];k++)
                f[x][j]=max(f[x][j],f[u][k]+f[x][j-k]);
        siz[x]+=siz[u];
    }
}
bool ck(double k)
{
    for(int i=1;i<=n;i++)a[i]=1.0*w[i]-1.0*s[i]*k;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)f[i][j]=-1e9;//
    dfs(0);
    return f[0][m]>=0;
}
int main()
{
    m=rd()+1; n=rd(); double l=0,r=0;//+1
    for(int i=1,fa;i<=n;i++)
    {
        s[i]=rd(); w[i]=rd(); fa=rd();
        add(fa,i); r+=w[i];
    }
    while(l-r<=eps)
    {
        double mid=(l+r)/2;
        if(ck(mid))ans=mid,l=mid+eps;
        else r=mid-eps;
    }
    printf("%.3lf\n",ans);
    return 0;
}

 

posted @ 2018-09-26 17:25  Zinn  阅读(138)  评论(0编辑  收藏  举报