这是一份 O(nm2) 的背包代码:
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,k 的上界都改成对应的子树容量和就会变成 O(nm)。但是个人感觉是 O(m2) 的,比如一个点权均为 m/n 的菊花图。求助此做法是否正确。如果正确求证明。
而那个神奇的严格 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背包)
}
}
求大佬解释。