1. 程式人生 > >BZOJ4753: [Jsoi2016]最佳團體

BZOJ4753: [Jsoi2016]最佳團體

規劃 span fin com printf OS pen n) 裏的

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 題目傳送門 這道垃圾題。。。我tm調了一天。。TLE到吐 一眼01分數規劃,然後二分。。最後樹形DP 然後。。有個喪病的家夥卡掉了我的做法。。。。 以後再填吧 大家幫忙看一下TLE代碼,該怎麽改進 多謝! 代碼如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include
<cstdlib> #include<algorithm> #define eps 1e-4 #define INF 1<<25 using namespace std; struct node{ int x,y,next; }a[4100000];int len,last[4100000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int n,m; double tot[2510],cost[2510
]; int d[2510]; double f[2510][2510]; int mem[2510]; void treedp(int x,double C) { f[x][0]=0.0; f[x][1]=tot[x]-C*cost[x];mem[x]=1; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; treedp(y,C); for(int i=m;i>1;i--) for(int j=0;j<=mem[y];j++) { if(i-j>=1) f[x][i]=max(f[x][i],f[y][j]+f[x][i-j]); else break; } mem[x]+=mem[y]; } } bool check(double C) { memset(mem,0,sizeof(mem)); memset(f,-INF,sizeof(f)); treedp(0,C); if(f[0][m]>=0.0)return true; return false; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d",&m,&n);len=0; for(int i=1;i<=n;i++) { scanf("%lf%lf%d",&cost[i],&tot[i],&d[i]); ins(d[i],i); } double l=0.0,r=3.0; double mid,ans=0.0; while(l<r) { mid=(l+r)/2; if(check(mid)==true){ans=mid,l=mid+eps;} else r=mid-eps; } printf("%.3lf\n",ans); return 0; }

by_lmy

BZOJ4753: [Jsoi2016]最佳團體