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

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. #define ll long long
  9. #define N 510
  10. #define M 4010
  11. #define inf 1000000000
  12. char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
  13. int gcd(int n,int m){return m==?n:gcd(m,n%m);}
  14. int read()
  15. {
  16. int x=,f=;char c=getchar();
  17. while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
  18. while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
  19. return x*f;
  20. }
  21. int n,m,w[N],c[N],d[N],p[N],t,cnt,ans;
  22. int size[N],dfn[N],id[N],f[N][M];
  23. bool flag[N];
  24. struct data{int to,nxt;
  25. }edge[N<<];
  26. void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
  27. void getsize(int k,int from)
  28. {
  29. size[k]=;
  30. for (int i=p[k];i;i=edge[i].nxt)
  31. if (edge[i].to!=from&&!flag[edge[i].to])
  32. {
  33. getsize(edge[i].to,k);
  34. size[k]+=size[edge[i].to];
  35. }
  36. }
  37. int findroot(int k,int from,int s)
  38. {
  39. int mx=;
  40. for (int i=p[k];i;i=edge[i].nxt)
  41. if (edge[i].to!=from&&!flag[edge[i].to]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
  42. if ((size[mx]<<)>s) return findroot(mx,k,s);
  43. else return k;
  44. }
  45. void dfs(int k,int from)
  46. {
  47. dfn[k]=++cnt;size[k]=;id[cnt]=k;
  48. for (int i=p[k];i;i=edge[i].nxt)
  49. if (edge[i].to!=from&&!flag[edge[i].to])
  50. {
  51. dfs(edge[i].to,k);
  52. size[k]+=size[edge[i].to];
  53. }
  54. }
  55. void solve(int k)
  56. {
  57. getsize(k,k);
  58. flag[k=findroot(k,k,size[k])]=;
  59. cnt=;dfs(k,k);
  60. memset(f[size[k]+],,sizeof(f[size[k]+]));
  61. //for (int i=1;i<=n;i++) cout<<size[i]<<' ';cout<<endl;
  62. //for (int i=1;i<=n;i++) cout<<dfn[i]<<' ';cout<<endl;
  63. //for (int i=1;i<=n;i++) cout<<id[i]<<' ';cout<<endl;
  64. //cout<<endl;
  65. for (int i=size[k];i;i--)
  66. {
  67. int x=id[i];
  68. for (int j=;j<=m;j++)
  69. if (j>=c[x]) f[i][j]=f[i+][j-c[x]]+w[x];
  70. else f[i][j]=-inf;
  71. int y=d[x];
  72. for (int u=;u<=;u++)
  73. if (y)
  74. {
  75. int z=min(y,<<u);
  76. for (int j=m;j>=c[x]*z;j--)
  77. f[i][j]=max(f[i][j],f[i][j-c[x]*z]+w[x]*z);
  78. y-=z;
  79. }
  80. for (int j=;j<=m;j++)
  81. f[i][j]=max(f[i][j],f[i+size[x]][j]);
  82. }
  83. ans=max(ans,f[][m]);
  84. for (int i=p[k];i;i=edge[i].nxt)
  85. if (!flag[edge[i].to]) solve(edge[i].to);
  86. }
  87. int main()
  88. {
  89. #ifndef ONLINE_JUDGE
  90. freopen("bzoj4182.in","r",stdin);
  91. freopen("bzoj4182.out","w",stdout);
  92. const char LL[]="%I64d\n";
  93. #else
  94. const char LL[]="%lld\n";
  95. #endif
  96. int T=read();
  97. while (T--)
  98. {
  99. n=read(),m=read();memset(p,,sizeof(p));t=ans=;
  100. for (int i=;i<=n;i++) w[i]=read();
  101. for (int i=;i<=n;i++) c[i]=read();
  102. for (int i=;i<=n;i++) d[i]=read()-;
  103. for (int i=;i<n;i++)
  104. {
  105. int x=read(),y=read();
  106. addedge(x,y),addedge(y,x);
  107. }
  108. memset(flag,,sizeof(flag));solve();
  109. printf("%d\n",ans);
  110. }
  111. return ;
  112. }

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学习之基础知识九 — 数据存储(持久化技术)之SQLite数据库存储

    前面一讲介绍了数据持久化技术的前两种:文件存储.SharedPreferences存储.下面介绍第三种技术:SQLite数据库存储 一.SQLite数据库存储 SQLite数据库是一款轻量级的关系型数 ...

  2. MySQL(十四)管理维护及性能优化

    关于MySQL的学习,<MySQL必知必会>这本书呢,看完已经两个月了,一直被工作以及生活的一些琐事拖着,趁着今晚有空闲,就整理完了最后的几章学习笔记,接下来的学习计划呢, 应该是pyth ...

  3. 开放的dae模型

    从网上看到了这段代码,就Copy过来了. 其实面对dae这种开放的模型格式,我们可以做很多事情,就像通常的XML文件一样. //------------------------------------ ...

  4. Linux下安装解压版(tar.gz)MySQL5.7

            最近尝试在Linux中安装了解压版MySQL,期间查阅了许多博客.很多博客看得我很懵逼,因此记录下自己的安装过程,方便后续查阅.         环境说明:CentOs7.2 一.清理 ...

  5. [Spark][python]RDD的collect 作用是什么?

    [Spark][Python]sortByKey 例子的继续 RDD的collect() 作用是什么? “[Spark][Python]sortByKey 例子”的继续 In [20]: mydata ...

  6. Stencil 基础

    Stencil 一个轻量化,渐进式编译器,注意,不是框架. 使用 TypeScript 进行所有操作,这是一个门槛,有一定技术门槛要求. PS:个人强烈推荐所有的前端同学都学习,或至少了解这个超集语言 ...

  7. ExtJS框架基础:事件模型及其常用功能

    前言 工作中用ExtJS有一段时间了,Ext丰富的UI组件大大的提高了开发B/S应用的效率.虽然近期工作中天天都用到ExtJS,但很少对ExtJS框架原理性的东西进行过深入学习,这两天花了些时间学习了 ...

  8. mysql操作命令梳理(1)-索引

    1.创建索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KE ...

  9. JavaScript之命名空间模式

    前言 命名空间可以被认为是唯一标识符下代码的逻辑分组.为什么会出现命名空间这一概念呢?因为可用的单词数太少,并且不同的人写的程序不可能所有的变量都没有重名现象.在JavaScript中,命名空间可以帮 ...

  10. 读书笔记(chapter4)

    进程调度 4.1多任务 1.多任务系统可以划分为:非抢占式多任务和抢占式多任务: (在此模式下,由调度程序来决定什么时候停止一个进程的运行,以便其他进程能够得到执行机会,这个动作叫抢占: 时间片实际上 ...