BZOJ 4753: [Jsoi2016]最佳团体 树形背包 01分数规划

来源:互联网 发布:淘宝买快排精密管安全 编辑:程序博客网 时间:2024/06/07 06:49

4753: [Jsoi2016]最佳团体

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 583  Solved: 242
[Submit][Status][Discuss]

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

分数规划就不多说了,二分就行

比较好的就是这个n^2的树形背包

详见这里


#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#include<iomanip>#include<vector>#include<string>#include<bitset>#include<queue>#include<set>#include<map>using namespace std;typedef double db;inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}void print(int x){if(x<0)x=-x,putchar('-');if(x>=10)print(x/10);putchar(x%10+'0');}const int N=2510;const db eps=1e-7;int ecnt,last[N];struct EDGE{int to,nt;}e[N<<1];inline void add(int u,int v){e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}int n,K,S[N],P[N];db a[N],f[N][N];int size[N];void dfs(int u){size[u]=1;for(int i=last[u];i;i=e[i].nt){dfs(e[i].to);size[u]+=size[e[i].to];}}void solve(int u){memset(f[u],0Xc2,sizeof(f[u]));int tot=0,b=0;if(u)f[u][1]=a[u],tot++,b++;else f[u][0]=0;for(int i=last[u];i;i=e[i].nt){solve(e[i].to);for(int j=tot;j>=b;--j)for(int k=1;k<=size[e[i].to];++k)f[u][j+k]=max(f[u][j+k],f[u][j]+f[e[i].to][k]);tot+=size[e[i].to];}}inline bool judge(db x){register int i;for(i=1;i<=n;++i)a[i]=P[i]-S[i]*x;solve(0);return f[0][K]>0-eps;}int main(){K=read();n=read();register int i,x;db l=0,r=0,mid;for(i=1;i<=n;++i)S[i]=read(),P[i]=read(),x=read(),add(x,i),r=max(double(P[i]),r);dfs(0);while(r-l>eps){mid=(l+r)/2;judge(mid)?l=mid:r=mid;}printf("%.3lf\n",l);}/*1 21000 1 01 1000 10.001*/

原创粉丝点击