E95 01分数规划+树上背包 P1642 规划
视频链接:E95 01分数规划+树上背包 P1642 规划_哔哩哔哩_bilibili


A07 01分数规划 - 董晓 - 博客园 (cnblogs.com)
P1642 规划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 01分数规划+树上背包 复杂度:n*m*log(1e9) #include <bits/stdc++.h> using namespace std; int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0';c=getchar();} return f*x; } const int N=105,Inf=1<<30; int head[N],idx; struct E{int to,ne;}e[N<<1]; int n,m,a[N],b[N],sz[N]; double c[N],f[N][N]; void add(int u,int v){ e[++idx]={v,head[u]}; head[u]=idx; } void dfs(int u,int fa){ sz[u]=1; f[u][0]=0; for(int i=head[u];i;i=e[i].ne){ int v=e[i].to; if(v==fa) continue; dfs(v,u); sz[u]+=sz[v]; for(int j=min(m,sz[u]);j>=0;j--) //容量 for(int k=0;k<=min(j,sz[v]);k++) //决策 f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); } for(int i=min(m,sz[u]);i>0;i--) f[u][i]=f[u][i-1]+c[u]; } bool check(double x){ for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) f[i][j]=-Inf; for(int i=1;i<=n;i++) c[i]=a[i]-x*b[i]; dfs(1,0); for(int i=1;i<=n;i++) if(f[i][m]>=0) return 1; return 0; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=read(); m=n-m; for(int i=1;i<n;i++){ int a=read(),b=read(); add(a,b); add(b,a); } double l=0,r=1000000; while(r-l>1e-3){ double mid=(l+r)/2; if(check(mid)) l=mid; else r=mid; } printf("%.1lf\n",l); }
浙公网安备 33010602011771号