[树形DP]JZOJ 4512 最佳团队
分析
我们可以二分答案,然后假设二分出的比例为a,则有
那么我们只需有最后得到的总和大于等于0即可
方程很简单,不过数据比较水,O(n^3logans)也是可以过的,那就简单的过掉吧
#include <iostream> #include <cstdio> #include <memory.h> using namespace std; const int N=2.5e3+10; const double eps=1e-5; struct Edge { int u,v,nx; }g[N]; int cnt,list[N],c[N],w[N],sz[N]; double f[N][N],l,r,mid; int k,n; void Add(int u,int v) { g[++cnt]=(Edge){u,v,list[u]};list[u]=cnt; } void DFS(int u,int last) { sz[u]=1;if (!last) return; for (int i=list[u];i;i=g[i].nx) { DFS(g[i].v,last-1);sz[u]+=sz[g[i].v]; for (int j=min(last-1,sz[u]);j;j--) for (int l=min(j,sz[g[i].v]);l;l--) f[u][j]=max(f[u][j],f[g[i].v][l]+f[u][j-l]); } for (int i=min(last,sz[u]);i;i--) f[u][i]=f[u][i-1]+w[u]-mid*c[u]; } int main() { scanf("%d%d",&k,&n); for (int i=1,fa;i<=n;i++) scanf("%d%d%d",&c[i],&w[i],&fa),Add(fa,i); r=1e4; while (r-l>eps) { mid=(l+r)/2;memset(f,0xf7,sizeof f); for (int i=0;i<=n;i++) f[i][0]=0; DFS(0,k+1); if (f[0][k+1]>=0) l=mid+eps; else r=mid-eps; } printf("%.3lf",(l+r)/2); }
在日渐沉没的世界里,我发现了你。