zoukankan      html  css  js  c++  java
  • luoguP6326 Shopping

    题意

    考虑点分治来枚举树上联通块,对于一个联通块,我们做有依赖性的树形DP即可,需要用单调队列优化多重背包。

    有依赖性的树形DP

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=510;
    const int maxm=4010;
    int T,n,m,ans;
    int val[maxn],cost[maxn],num[maxn];
    inline int read()
    {
        char c=getchar();int res=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
        return res*f;
    }
    int cnt_edge;
    int head[maxn];
    struct edge{int to,nxt;}e[maxn<<1];
    inline void add_edge(int u,int v)
    {
    	e[++cnt_edge]=(edge){v,head[u]};
    	head[u]=cnt_edge;
    }
    int root,trsize;
    int size[maxn],maxs[maxn];
    bool vis[maxn];
    void getroot(int x,int fa)
    {
    	size[x]=1;maxs[x]=0;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa||vis[y])continue;
    		getroot(y,x);size[x]+=size[y];
    		maxs[x]=max(maxs[x],size[y]);
    	}
    	maxs[x]=max(maxs[x],trsize-size[x]);
    	if(maxs[x]<maxs[root])root=x;
    }
    int cnt;
    int a[maxn],q[maxn];
    int f[maxn][maxm];
    void dfs(int x,int fa)
    {
    	size[a[++cnt]=x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa||vis[y])continue;
    		dfs(y,x);size[x]+=size[y];
    	}
    }
    inline void dp()
    {
    	for(int i=cnt;i;i--)
    	{
    		int x=a[i];
    		for(int j=1;j<=m;j++)f[i][j]=f[i+size[x]][j];
    		for(int j=0;j<cost[x];j++)
    		{
    			int l=1,r=0,up=(m-j)/cost[x];
    			for(int k=up-1;k>=max(0,up-num[x]);k--)
    			{
    				while(l<=r&&f[i+1][j+q[r]*cost[x]]-q[r]*val[x]<=f[i+1][j+k*cost[x]]-k*val[x])r--;
    				q[++r]=k;
    			}
    			for(int k=up;~k;k--)
    			{
    				while(l<=r&&q[l]>k-1)l++;
    				if(l<=r)f[i][j+k*cost[x]]=max(f[i][j+k*cost[x]],f[i+1][j+q[l]*cost[x]]+(k-q[l])*val[x]);
    				if(k-num[x]-1>=0)
    				{
    					int now=k-num[x]-1;
    					while(l<=r&&f[i+1][j+q[r]*cost[x]]-q[r]*val[x]<=f[i+1][j+now*cost[x]]-now*val[x])r--;
    					q[++r]=now;
    				}
    			}
    		}
    	}
    	for(int i=0;i<=m;i++)ans=max(ans,f[1][i]);
    	for(int i=1;i<=cnt;i++)
    		for(int j=0;j<=m;j++)
    			f[i][j]=0;
    }
    void solve(int x)
    {
    	cerr<<"now::"<<x<<endl;
    	vis[x]=1;
    	cnt=0;dfs(x,0);dp();
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(vis[y])continue;
    		trsize=size[y],root=0,getroot(y,0),solve(root);
    	}
    }
    inline void solve()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)val[i]=read();
    	for(int i=1;i<=n;i++)cost[i]=read();
    	for(int i=1;i<=n;i++)num[i]=read();
    	for(int i=1;i<n;i++)
    	{
    		int u=read(),v=read();
    		add_edge(u,v),add_edge(v,u);
    	}
    	trsize=maxs[root=0]=n;getroot(1,0);solve(root);
    	printf("%d
    ",ans);
    }
    inline void init()
    {
    	memset(head,0,sizeof(head));
    	memset(vis,0,sizeof(vis));
    	cnt_edge=ans=0;
    }
    int main()
    {
    	int T=read();
    	while(T--)init(),solve();
    	return 0;
    }
    
    
  • 相关阅读:
    JS加密对应的c#解码
    Content-Type: application/www-form-urlencoded
    使用abcpdf分页设置的问题
    Windows10远程报错:由于CredSSP加密Oracle修正
    ueditorUE 去掉本地保存成功的提示框!
    js进制转换
    缓存穿透 缓存雪崩 缓存击穿
    DTcms 模版用vs2015或2017 打开编辑时候 粘贴出问题 代码被调整
    通俗简述 依赖倒置•控制反转•依赖注入•面向接口编程 的思想
    tcp/ip
  • 原文地址:https://www.cnblogs.com/nofind/p/13049552.html
Copyright © 2011-2022 走看看