点分治,每次考虑包含根的连通块,做树形多重背包即可,dfs序优化。注意题面给的di范围是假的,坑了我0.5h,心态炸了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 510
#define M 4010
#define inf 1000000000
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,w[N],c[N],d[N],p[N],t,cnt,ans;
int size[N],dfn[N],id[N],f[N][M];
bool flag[N];
struct data{int to,nxt;
}edge[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void getsize(int k,int from)
{
size[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to])
{
getsize(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
int findroot(int k,int from,int s)
{
int mx=;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
if ((size[mx]<<)>s) return findroot(mx,k,s);
else return k;
}
void dfs(int k,int from)
{
dfn[k]=++cnt;size[k]=;id[cnt]=k;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&!flag[edge[i].to])
{
dfs(edge[i].to,k);
size[k]+=size[edge[i].to];
}
}
void solve(int k)
{
getsize(k,k);
flag[k=findroot(k,k,size[k])]=;
cnt=;dfs(k,k);
memset(f[size[k]+],,sizeof(f[size[k]+]));
//for (int i=1;i<=n;i++) cout<<size[i]<<' ';cout<<endl;
//for (int i=1;i<=n;i++) cout<<dfn[i]<<' ';cout<<endl;
//for (int i=1;i<=n;i++) cout<<id[i]<<' ';cout<<endl;
//cout<<endl;
for (int i=size[k];i;i--)
{
int x=id[i];
for (int j=;j<=m;j++)
if (j>=c[x]) f[i][j]=f[i+][j-c[x]]+w[x];
else f[i][j]=-inf;
int y=d[x];
for (int u=;u<=;u++)
if (y)
{
int z=min(y,<<u);
for (int j=m;j>=c[x]*z;j--)
f[i][j]=max(f[i][j],f[i][j-c[x]*z]+w[x]*z);
y-=z;
}
for (int j=;j<=m;j++)
f[i][j]=max(f[i][j],f[i+size[x]][j]);
}
ans=max(ans,f[][m]);
for (int i=p[k];i;i=edge[i].nxt)
if (!flag[edge[i].to]) solve(edge[i].to);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4182.in","r",stdin);
freopen("bzoj4182.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
int T=read();
while (T--)
{
n=read(),m=read();memset(p,,sizeof(p));t=ans=;
for (int i=;i<=n;i++) w[i]=read();
for (int i=;i<=n;i++) c[i]=read();
for (int i=;i<=n;i++) d[i]=read()-;
for (int i=;i<n;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
memset(flag,,sizeof(flag));solve();
printf("%d\n",ans);
}
return ;
}

BZOJ4182 Shopping(点分治+树形dp)的更多相关文章

  1. [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化)

    [BZOJ4182]Shopping (点分治+树上多重背包+单调队列优化) 题面 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树 ...

  2. [BZOJ2152]聪聪可可 点分治/树形dp

    2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MB Submit: 3602  Solved: 1858 [Submit][Status][Discu ...

  3. [codeforces161D]Distance in Tree(点分治/树形dp)

    题意:求树上距离为k的点对个数: 解题关键:练习一下点分治不用容斥 而直接做的做法.注意先查询,后更新. 不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些, ...

  4. BZOJ 2152 / Luogu P2634 [国家集训队]聪聪可可 (点分治/树形DP)

    题意 一棵树,给定边权,求满足两点之间的路径上权值和为3的倍数的点对数量. 分析 点分治板题,对每个重心求子树下面的到根的距离模3分别为0,1,2的点的个数就行了. O(3nlogn)O(3nlogn ...

  5. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

  6. E. Alternating Tree 树点分治|树形DP

    题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1)  注意是点有权值. 从上头往下考虑是点分治,从下向上考虑就是树形DP, ...

  7. 『You Are Given a Tree 整体分治 树形dp』

    You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...

  8. BZOJ4182: Shopping(点分治,树上背包)

    Description 马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街.商店街有n个商店,并且它们之间的道路构成了一颗树的形状. 第i个商店只卖第i种物品,小苗对于这种物品的喜爱度 ...

  9. bzoj4182 Shopping 点分治+单调队列优化多重背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4182 题解 有一个很直观的想法是设 \(dp[x][i]\) 表示在以 \(x\) 为根的子树 ...

随机推荐

  1. Android学习之基础知识五—创建自定义控件

    下面是控件和布局的继承关系: 从上面我们看到: 1.所有控件都是直接或间接继承View,所有的布局都是直接或间接继承ViewGroup 2.View是Android中最基本的UI组件,各种组件其实就是 ...

  2. linux笔记-多服务器同时执行相同命令

    1.服务器的ip地址写到文件中,命名为nodelist.txt 192.168.1.160 192.168.1.166 2.编写运行脚本 for i in `cat nodelist.txt`do s ...

  3. 2-微信小程序开发(开发界面说明,按钮点击切换显示内容)

    说一个功能,大家在用微信实现控制设备的时候,是不是都在为绑定设备发愁. 我看了很多厂家的微信控制,大部分都只是可以用微信给设备配网,但是没有做用微信绑定的. 一般做绑定都是用设备的MAC地址. 这里我 ...

  4. eclipse 如何引入本地dtd

    一.首先修改xml的打开方式为:XML editor 1.菜单:Window -> Preferences ->General -> Editors -> File  Asso ...

  5. 加解密工具类(含keystore导出pfx)

    java代码如下: package sign; import java.io.FileInputStream; import java.io.FileOutputStream; import java ...

  6. A2dp连接流程源码分析

    在上一篇文章中,我们已经分析了:a2dp初始化流程 这篇文章主要分析a2dp的连接流程,其中还是涉及到一些底层的profile以及protocol,SDP.AVDTP以及L2CAP等. 当蓝牙设备与主 ...

  7. markdown操作手册

    **1.标题** # h1 h1自带分割线 ## h2 ### h3 #### h4 ##### h5 ###### h6 **2.圆点** - 圆点 **3.分割线,-和*都可以** --- *** ...

  8. SQL Server扩充表字段长度,引发的意外KILLED/ROLLBACK

    这一段时间,因为系统升级,新系统产生的数据长度,比原来的数据长度要长,所以说要扩充一下字段长度. ) --修改字段长度sql 在执行的时候,有这样一个情况. 例如Student表的Name字段长度是n ...

  9. Indidual Homework Assignment

    一.Pair work的得与失 合作编程在以前的学习过程中也进行过,基本也就是各人负责一部分最后再将之拼凑起来,而这次作业要求的双人合作,要求的并不是这样,而是两人应该在一起进行工作,这样的要求理想情 ...

  10. junit4实验报告

    一:题目简介 测试一个加.减.乘.除. 二:源码的github链接 https://github.com/wangyuefang/test/blob/master/daiceshilei.md htt ...