第一次写树上背包,问个小问题
查看原帖
第一次写树上背包,问个小问题
205049
Emplace_back楼主2022/11/7 10:42

为什么这样写是错的?始终想不明白。

备注:以0为超级源点方便统计答案,m已经在main()中+1。

siz[]:子树大小 f[节点][已选科数]

void dfs(int u,int fa)
{
	siz[u]=1;
	for(int e=fir[u];e;e=nex[e])
	{
		int v=to[e];
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];
		if(siz[u]>m) siz[u]=m;
		for(int i=siz[u];i>=2;--i)
		{
			int tmp=min(i-1,siz[v]);
			for(int j=0;j<=tmp;++j)
				f[u][i]=max(f[u][i],f[v][j]+f[u][i-j-1]); //给点u腾一个位置,-1
		}
	}
	for(int i=1;i<=siz[u];++i) f[u][i]+=val[u]; //最后再把节点u的贡献加上
}

这样子就对了:

void dfs(int u,int fa)
{
	siz[u]=1;
	f[u][1]=val[u]; //背包预处理
	for(int e=fir[u];e;e=nex[e])
	{
		int v=to[e];
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];
		if(siz[u]>m) siz[u]=m;
		for(int i=siz[u];i>=2;++i)
		{
			int tmp=min(i-1,siz[v]);
			for(int j=0;j<=tmp;++j)
				f[u][i]=max(f[u][i],f[v][j]+f[u][i-j]);
		}
	}
}

But Why? qwq

2022/11/7 10:42
加载中...