zoukankan      html  css  js  c++  java
  • 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
    ",ans);
    144     }
    145     return 0;
    146 }
  • 相关阅读:
    openssh升级到openssh-7.5p1踩坑
    office online server部署和简单操作
    aspnetmvc和aspnetcoremvc的一些区别
    office web app server部署和简单操作
    PHP之cURL
    认识PHP的全局变量
    认识Linux系统/etc/hosts
    git学习——stash命令(4)
    Linux netstat命令
    phpstorm+xdebug
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10159474.html
Copyright © 2011-2022 走看看