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; }