
2.求解方法

例题1 P1642 规划
模板题 二分c后,check方法:利用树形dp求ai-bi*c的最大值
树形dp方法:dis[i][j]表示i子树中选j个的最大值
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
const int inf=0x3f3f3f3f;
double l=0,r=100000,mid,eps=1e-5;
double f[maxn][maxn],tmp[maxn];
int n,m,head[maxn],cnt;
int c[maxn],w[maxn];
struct edge
{
int to,nxt;
}e[maxn<<1];
void add(int x,int y)
{
e[++cnt].to=y; e[cnt].nxt=head[x]; head[x]=cnt;
}
void dfs(int u,int fa)
{
f[u][0]=0;
for(int i=head[u];i;i=e[i].nxt)
{
int to=e[i].to;
if(to==fa) continue;
dfs(to,u);
for(int j=m-1;j>=0;j--)
for(int k=0;k<=j;k++)
f[u][j]=max(f[u][j],f[u][j-k]+f[to][k]);
}
for(int i=m;i>=1;i--) f[u][i]=f[u][i-1]+tmp[u];
}
bool check(double x)
{
memset(f,-inf,sizeof(f));
for(int i=1;i<=n;i++)
tmp[i]=c[i]*1.0-x*(w[i]*1.0);
dfs(1,0);
for(int i=1;i<=n;i++)
if(f[i][m]>-eps) return 1;
return 0;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d",&n,&m);
m=n-m;
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
while(r-l>eps)
{
mid=(l+r)/2.0;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.1lf",l);
return 0;
}
1457

被折叠的 条评论
为什么被折叠?



