zoukankan      html  css  js  c++  java
  • bzoj4182 Shopping

    题目描述:

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

    第i个商店只卖第i种物品,小苗对于这种物品的喜爱度是wi,物品的价格为ci,物品的库存是di。

    但是商店街有一项奇怪的规定:如果在商店 u,v买了东西,并且有一个商店w在u到v的路径上,那么必须要在商店w买东西。

    小葱身上有m元钱,他想要尽量让小苗开心,所以他希望最大化小苗对买到物品的喜爱度之和。

    这种小问题对于小葱来说当然不在话下,但是他的身边没有电脑,于是他打电话给同为OI选手的你,你能帮帮他吗?

    题解:

    我们可以发现,选择的一定是个联通块。

    这就似乎是树上背包。

    由于根不确定而且有依赖性,我们可以通过点分治的性质优化背包。

    有点恶心。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 550
    #define M 4050
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    int T,n,m,hed[N],cnt;
    int w[N],c[N],d[N];
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int mrk[N],ans;
    int rt,v[N],siz[N],sum;
    void get_rt(int u,int fa)
    {
        v[u] = 0,siz[u] = 1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa||mrk[to])continue;
            get_rt(to,u);
            siz[u]+=siz[to];
            if(siz[to]>v[u])v[u]=siz[to];
        }
        v[u] = max(v[u],sum-siz[u]);
        if(v[u]<v[rt])rt=u;
    }
    int f[N][M];
    void dfs(int u,int fa,int lim)
    {
        if(lim<=0)return ;
        int i,j;
        for(i=1,j=d[u];i<j;j-=i,i<<=1)
            for(int k=lim;k>=i*c[u];k--)
                f[u][k] = max(f[u][k],f[u][k-i*c[u]]+i*w[u]);
        for(int k=lim;k>=j*c[u];k--)
            f[u][k] = max(f[u][k],f[u][k-j*c[u]]+j*w[u]);
        for(j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to]||to==fa)continue;
            for(i=0;i<=lim-c[to];i++)f[to][i]=f[u][i]+w[to];
            dfs(to,u,lim-c[to]);
            for(i=0;i<=lim-c[to];i++)f[u][i+c[to]]=max(f[u][i+c[to]],f[to][i]);
        }
    }
    void work(int u)
    {
        mrk[u] = 1;
        for(int i=0;i<=m-c[u];i++)f[u][i] = w[u];
        dfs(u,0,m-c[u]);
        for(int i=0;i<=m-c[u];i++)ans = max(ans,f[u][i]);
        int sm0 = sum;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            rt=0,sum=(siz[to]>siz[u]?sm0-siz[u]:siz[to]);
            get_rt(to,0);
            work(rt);
        }
    }
    void init()
    {
        cnt=ans=0;
        memset(hed,0,sizeof(hed));
        memset(mrk,0,sizeof(mrk));
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        T = rd();
        v[0]=0x7fffffff;
        while(T--)
        {
            init();
            n = rd(),m = rd();
            for(int i=1;i<=n;i++)w[i]=rd();
            for(int i=1;i<=n;i++)c[i]=rd();
            for(int i=1;i<=n;i++)d[i]=rd()-1;
            for(int f,t,i=1;i<n;i++)
            {
                f=rd(),t=rd();
                ae(f,t),ae(t,f);
            }
            rt=0,sum=n;
            get_rt(1,0);
            work(rt);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Sobel算子 (转)
    由矩阵运算来看初等矩阵的左乘右乘所影响到矩阵的行列变换的本质(转)
    矩阵的迹(转)
    深度神经网络识别图形图像的基本原理(转)
    图解卷积神经网络(二)(转)
    Matlab 的reshape函数(转)
    iOS关键词weak和assign的区别
    网络层HTPPS和HTTP的概念与区别
    iOS开发之#impor与#include的区别
    iOS制作自己的Framework框架
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10190044.html
Copyright © 2011-2022 走看看