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;
    }
    
    
  • 相关阅读:
    WPF ComboBox 控件用法
    WPF 调试办法
    wpf Border 装饰控件用法
    创建型模式:抽象工厂(Abstract Factory)
    创建型模式:工厂方法
    使用FreeSpire.Doc不安装Office组件的情况下操作Word文件
    【算法一】布隆过滤器算法学习附维基百科详细说明PDF文件
    C# 读写锁解决多线程下并发写入文件报异常“文件正在由另一进程使用,因此该进程无法访问此文件”的解决办法
    多线程下System.Threading.Interlocked用法
    WPF程序内嵌CEF框架浏览网站
  • 原文地址:https://www.cnblogs.com/nofind/p/13049552.html
Copyright © 2011-2022 走看看