luoguP6326 Shopping

Posted nofind

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于luoguP6326 Shopping的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4182/luoguP6326 Shopping(点分治,树上背包)

HDU 6326 Problem H Monster Hunter

[HDU6326]Monster Hunter(贪心)

作业购物车

react1

shopping_list(刚开始学python)