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

Description

马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街。商店街有n个商店,并且它们之间的道路构成了一颗树的形状。

第i个商店只卖第i种物品,小苗对于这种物品的喜爱度是wi,物品的价格为ci,物品的库存是di。但是商店街有一项奇怪的规定:如果在商店u,v买了东西,并且有一个商店w在u到v的路径上,那么必须要在商店w买东西。小葱身上有m元钱,他想要尽量让小苗开心,所以他希望最大化小苗对买
到物品的喜爱度之和。这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为OI选手的你,你能帮帮他吗?

Input

输入第一行一个正整数T,表示测试数据组数。

对于每组数据,
第一行两个正整数n;m;
第二行n个非负整数w1,w2...wn;
第三行n个正整数c1,c2...cn;
第四行n个正整数d1,d2...dn;
接下来n-1行每行两个正整数u;v表示u和v之间有一条道路

Output

输出共T 行,每行一个整数,表示最大的喜爱度之和。

Sample Input

1
3 2
1 2 3
1 1 1
1 2 1
1 2
1 3

Sample Output

4

解题思路:

可以发现答案最后是一颗子树,所以我们只需要枚举子树就好了,由于根节点不定,所以靠点分治来实现枚举根(如果答案比一个子树大,那么一点会经过这个根),Dfs序跑出来做树形背包就好了。

多重背包二进制拆分一下就好了。

代码:

 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 typedef long long lnt;
  5 const int N=510;
  6 const int M=4010;
  7 struct pnt{
  8     int hd;
  9     int wgt;
 10     int w;
 11     int c;
 12     int d;
 13     int ind;
 14     int oud;
 15     bool vis;
 16 }p[N],stp;
 17 struct ent{
 18     int twd;
 19     int lst;
 20 }e[N<<1];
 21 int T,n,m;
 22 int cnt;
 23 int dfn;
 24 int size;
 25 int root;
 26 int maxsize;
 27 lnt ans;
 28 int lin[N];
 29 lnt dp[N][M];
 30 void ade(int f,int t)
 31 {
 32     cnt++;
 33     e[cnt].twd=t;
 34     e[cnt].lst=p[f].hd;
 35     p[f].hd=cnt;
 36     return ;
 37 }
 38 void grc_dfs(int x,int f)
 39 {
 40     p[x].wgt=1;
 41     int maxs=-1;
 42     for(int i=p[x].hd;i;i=e[i].lst)
 43     {
 44         int to=e[i].twd;
 45         if(to==f||p[to].vis)
 46             continue;
 47         grc_dfs(to,x);
 48         p[x].wgt+=p[to].wgt;
 49         if(maxs<p[to].wgt)
 50             maxs=p[to].wgt;
 51     }
 52     maxs=std::max(maxs,size-p[x].wgt);
 53     if(maxs<maxsize)
 54     {
 55         root=x;
 56         maxsize=maxs;
 57     }
 58     return ;
 59 }
 60 void Build_dfs(int x,int f)
 61 {
 62     lin[++dfn]=x;
 63     p[x].ind=dfn;
 64     for(int i=p[x].hd;i;i=e[i].lst)
 65     {
 66         int to=e[i].twd;
 67         if(to==f||p[to].vis)
 68             continue;
 69         Build_dfs(to,x);
 70     }
 71     p[x].oud=dfn;
 72     return ;
 73 }
 74 void bin_dfs(int x)
 75 {
 76     p[x].vis=true;
 77     dfn=0;
 78     Build_dfs(x,x);
 79     for(int i=0;i<=dfn+1;i++)
 80         for(int j=0;j<=m;j++)
 81             dp[i][j]=0;
 82     for(int i=dfn;i;i--)
 83     {
 84         int t=lin[i];
 85         int w=p[t].d-1;
 86         for(int j=m;j>=p[t].c;j--)
 87             dp[i][j]=dp[i+1][j-p[t].c]+p[t].w;
 88         for(int j=1;;j<<=1)
 89         {
 90             if(w<j)
 91                 j=w;
 92             for(int k=m;k>=j*p[t].c;k--)
 93                 dp[i][k]=std::max(dp[i][k],dp[i][k-j*p[t].c]+j*p[t].w);
 94             w-=j;
 95             if(!w)
 96                 break;
 97         }
 98         for(int j=0;j<=m;j++)
 99             dp[i][j]=std::max(dp[i][j],dp[p[t].oud+1][j]);
100     }
101     ans=std::max(ans,dp[1][m]);
102     for(int i=p[x].hd;i;i=e[i].lst)
103     {
104         int to=e[i].twd;
105         if(p[to].vis)
106             continue;
107         root=0;
108         size=p[to].wgt;
109         maxsize=0x3f3f3f3f;
110         grc_dfs(to,to);
111         bin_dfs(root);
112     }
113     return ;
114 }
115 int main()
116 {
117     //freopen("a.in","r",stdin);
118     scanf("%d",&T);
119     while(T--)
120     {
121         scanf("%d%d",&n,&m);
122         for(int i=1;i<=n;i++)
123             p[i]=stp;
124         cnt=0,ans=0;
125         for(int i=1;i<=n;i++)
126             scanf("%d",&p[i].w);
127         for(int i=1;i<=n;i++)
128             scanf("%d",&p[i].c);
129         for(int i=1;i<=n;i++)
130             scanf("%d",&p[i].d);
131         for(int i=1;i<n;i++)
132         {
133             int a,b;
134             scanf("%d%d",&a,&b);
135             ade(a,b);
136             ade(b,a);
137         }
138         root=0;
139         size=n;
140         maxsize=0x3f3f3f3f;
141         grc_dfs(1,1);
142         bin_dfs(root);
143         printf("%lld\n",ans);
144     }
145     return 0;
146 }

 

posted @ 2018-12-21 23:12  Unstoppable728  阅读(272)  评论(0编辑  收藏  举报