• 题解 洛谷 P6326 【Shopping】


    考虑若连通块必须包含 (x),那么就对以 (x) 为根的有根树做树形背包。

    (f_{i,j}) 为考虑了 (dfs) 序中 ([i,n]) 对应的节点,体积为 (j) 的最大价值。转移分两种情况:一个是选 (i) 对应的节点,然后对该节点的物品跑多重背包,我这里用的是二进制拆分来优化。另一个是不选 (i) 对应的节点,然后从该节点子树外转移过来,这里可以在 (dfs) 序上表示转移的位置。

    连通块不包含 (x) 的情况可以用点分治来递归处理。

    复杂度为 (O(nmlog dlog n))

    #include<bits/stdc++.h>
    #define maxn 1010
    #define maxm 4010
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int T,n,m,ans,tot,root,cnt;
    int w[maxn],c[maxn],d[maxn],f[maxn][maxm],siz[maxn],mx[maxn],out[maxn],rev[maxn];
    bool vis[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]={to,head[from]},head[from]=edge_cnt;
    }
    struct node
    {
        int v,w;
    }p[maxn];
    void dfs_root(int x,int fa)
    {
        siz[x]=1,mx[x]=0;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(vis[y]||y==fa) continue;
            dfs_root(y,x),siz[x]+=siz[y];
            mx[x]=max(mx[x],siz[y]);
        }
        mx[x]=max(mx[x],tot-siz[x]);
        if(mx[x]<mx[root]) root=x;
    }
    void dfs_dfn(int x,int fa)
    {
        rev[++cnt]=x;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(vis[y]||y==fa) continue;
            dfs_dfn(y,x);
        }
        out[x]=cnt;
    }
    void solve(int x)
    {
        vis[x]=true,cnt=0,dfs_dfn(x,0);
        for(int i=cnt;i;--i)
        {
            int s=d[rev[i]]-1,num=0;
            for(int j=1;j<=s;s-=j,j<<=1) p[++num]={w[rev[i]]*j,c[rev[i]]*j};
            if(s) p[++num]={w[rev[i]]*s,c[rev[i]]*s};
            for(int j=m;j>=c[rev[i]];--j) f[i][j]=f[i+1][j-c[rev[i]]]+w[rev[i]];
            for(int k=1;k<=num;++k)
                for(int j=m;j>=p[k].w;--j)
                    f[i][j]=max(f[i][j],f[i][j-p[k].w]+p[k].v);
            for(int j=0;j<=m;++j) f[i][j]=max(f[i][j],f[out[rev[i]]+1][j]);
        }
        ans=max(ans,f[1][m]);
        for(int i=1;i<=cnt;++i)
            for(int j=0;j<=m;++j)
                f[i][j]=0;
        int now=tot;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(vis[y]) continue;
            root=0,tot=siz[y];
            if(siz[y]>siz[x]) tot=now-siz[x];
            dfs_root(y,x),solve(root);
        }
    }
    void clear()
    {
        edge_cnt=root=ans=0;
        memset(vis,0,sizeof(vis));
        memset(head,0,sizeof(head));
    }
    int main()
    {
        read(T);
        while(T--)
        {
            clear(),read(n),read(m);
            for(int i=1;i<=n;++i) read(w[i]);
            for(int i=1;i<=n;++i) read(c[i]);
            for(int i=1;i<=n;++i) read(d[i]);
            for(int i=1;i<n;++i)
            {
                int x,y;
                read(x),read(y);
                add(x,y),add(y,x);
            }
            tot=mx[0]=n,dfs_root(1,0),solve(root),printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    10.flask博客项目实战五之用户登录功能
    09.flask博客项目实战四之数据库
    08.flask博客项目实战三之表单
    07.flask博客项目实战二之模板使用
    06.flask博客项目实战一之项目框架搭建
    05.flask数据库
    04.flask表单
    03.flask模板
    idea 灵异事件之maven 缓存
    如何查看Spring Boot 默认的数据库连接池类型
  • 原文地址:https://www.cnblogs.com/lhm-/p/13691042.html
Copyright © 2020-2023  润新知