求助树形背包
  • 板块学术版
  • 楼主masonpop
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/10/29 15:46
  • 上次更新2023/10/29 15:53:22
查看原帖
求助树形背包
614725
masonpop楼主2023/10/29 15:46

这是一份 O(nm2)O(nm^2) 的背包代码:

inline void dfs(int x,int fa)
{
	for(int i=v[x];i<=m;i++)f[x][i]=w[x];
	for(int i=head[x];i;i=nxt[i])
    	{
              int y=to[i];
              if(y==fa)continue;
              dfs(y,x);
              for(int j=m;j>=v[x];j--)
              {
                    for(int k=0;k<=j-v[x];k++)
                    {
                        f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);	
                    } 
              }
    	}
}

我看网上说把 j,kj,k 的上界都改成对应的子树容量和就会变成 O(nm)O(nm)。但是个人感觉是 O(m2)O(m^2) 的,比如一个点权均为 m/nm/n 的菊花图。求助此做法是否正确。如果正确求证明。

而那个神奇的严格 O(nm)O(nm) 做法我没有理解。代码大概长这样:

void dfs(int u,int t,int fa)
//u是当前节点,t是当前容量,fa是父亲节点
{
	if(t<=0)return;//装不下了
	for(int i=head[u];i;i=e[i].next)//访问与该点相连的每一条边
	{
		int v=e[i].to;
		if(v==fa)continue;//如果是父节点则跳过
		for(int k=N-w[v];k>=0;k--)
			dp[v][k]=dp[u][k]+c[v];//要选子树,就必须选该节点
		dfs(v,t-w[v],u);//继续递归
		for(int k=N;k>=w[v];k--)
			dp[u][k]=max(dp[u][k],dp[v][k-w[v]]);//选或不选(这是01背包)
	}
}

求大佬解释。

2023/10/29 15:46
加载中...