• P6326 Shopping


    题目

    P6326 Shopping

    分析

    首先发现很明显是树上多重背包。

    于是可以考虑设状态 (dp[x][i]) 表示(必选(x))和其子树连通块,且背包容量为 (i) 时的最大价值。

    直接单调队列 (dp) ,明显是 (O(n^2m))

    那么考虑优化,我们发现这里的难点无非就是要处理每一个点作为当前根,那么我们直接考虑点分治,然后根节点必选即可。

    同时,我们还是也可以考虑暴力枚举,因为这里没有强制在线,所以直接启发式合并也可以做到 (O(nmlogn))

    这里可以用二进制优化,好像还跑的快点,代码细节见这里

    代码

    这里是点分治做法。

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;bool f=false;char ch=getchar();
    	while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    } 
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    #define ll long long
    const int N=1005,V=4005;
    int t,n,m,Ans;
    int head[N],nex[N],to[N],idx;
    inline void add(int u,int v){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	head[u]=idx;
    	return ;
    }
    int w[N],c[N],d[N];
    int Root,FMax,siz[N],Size;
    bool vis[N];
    void GetRoot(int x,int fa){
    	siz[x]=1;int Max=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(y==fa||vis[y]) continue;
    		GetRoot(y,x);siz[x]+=siz[y];
    		Max=max(Max,siz[y]);
    	}
    	Max=max(Max,Size-siz[x]);
    	if(Max<=FMax) FMax=Max,Root=x;
    	return ;
    }
    int dp[N][V];
    void DP(int x,int fa,int lim){
    	if(lim-c[x]<0) return ;
    	int num=d[x]-1;
    	const int v=lim-c[x];
    	for(int i=0;i<=v;i++) dp[x][i]=dp[fa][i]+w[x];
    	for(int i=0;(1<<i)<=num;i++){
    		const int tmp=(1<<i);
    		for(int j=v;j>=c[x]*tmp;j--) dp[x][j]=max(dp[x][j],dp[x][j-c[x]*tmp]+w[x]*tmp);
    		num-=tmp; 
    	}
    	if(num){
    		const int tmp=num;
    		for(int j=v;j>=c[x]*tmp;j--) dp[x][j]=max(dp[x][j],dp[x][j-c[x]*tmp]+w[x]*tmp);
    		num-=tmp;
    	}
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(y==fa||vis[y]) continue;
    		DP(y,x,v); 
    		for(int j=c[y];j<=v;j++) dp[x][j]=max(dp[x][j],dp[y][j-c[y]]);
    	}
    	return ;
    }
    void Update(int x,int fa){
    	DP(x,0,m);
    	for(int i=0;i<=m-c[x];i++) Ans=max(Ans,dp[x][i]);
    	return ;
    }
    void DFS(int x,int fa){
    	vis[x]=true;Update(x,fa);
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]) continue;
    		Size=FMax=siz[y],Root=y,GetRoot(y,x),DFS(Root,x); 
    	}
    	vis[x]=false;
    	return ;
    }	 
    signed main(){
    	read(t);
    	while(t--){
    		read(n),read(m);
    		idx=0;Ans=0;
    		memset(head,0,sizeof(head));
    		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 u,v;
    			read(u),read(v);
    			add(u,v),add(v,u);
    		}
    		Size=FMax=n,Root=0,GetRoot(1,0),DFS(Root,0); 
    		write(Ans),putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    【转】请说出三种减少页面加载时间的方法。
    【转】Web前端性能优化——如何提高页面加载速度
    【转】数据分析sql常用整理
    【转】消息中间件系列之简单介绍
    Could not load file or assembly 'System.Core, Version=2.0.5.0 和autofac冲突的问题
    云主机与传统主机性能对比表
    真假云主机,VPS资料集合
    将网站部署到windows2003 iis6之后,出现asp.net程序页面无法访问情况
    想当然是编程最大的坑,记更新删除过期cookie无效有感
    FlashBuilder(FB/eclipse) 打开多个无效
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14728566.html
Copyright © 2020-2023  润新知