4753: [Jsoi2016]最佳团体
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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
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 2
1000 1 0
1 1000 1
0.001
*/