树形 DP 问题

树形 dp 问题

  • 最小点覆盖

问题:

给定一颗有 n 个点的有根树,从这 n 个点中选出尽量少的点,使得所有边都与取出来的点相连。

分析:

考虑一条边,它两端的节点必定有一个在所选点集中,可以考虑 dp :

fu,0 表示以 u 为根的子树中, u 不在点覆盖集中所需要选取的最小点数; fu,1 表示以 u 为根的子树中, u 在点覆盖集中所需要选取的最小点数。

接下来考虑转移 (其中 vu 的儿子):

对于 fu,0 ,因为 u 不选取,则 u 的儿子一定要取,所以 fu,0=fv,1

对于 fu,1 , 因为 u 要选取,则 u 的儿子可选可不选,所以 fu,1=1+min(fv,0,fv,1)

设根节点为 root ,则最后答案为 min(froot,0,froot,1)

int f[MAXN][2];
void Dfs(int u,int fa)
{
	f[u][0]=0;f[u][1]=1;
	for(int v:G[u])
	{
		if(v==fa) continue;
		Dfs(v,u);
		f[u][0]+=f[v][1];
		f[u][1]+=min(f[v][0],f[v][1]);
	}
}
  • 最大独立集

问题:

给定一棵有 n 个点的树,从 n 个点中选出尽量多的点,使得两两之间没有连边。

分析:

同上,考虑一条边,它两端的点不能被同时选取,那么考虑 dp

fu,0 表示以 u 为根的子树中 u 不在最大独立集中最多可以选多少点, fu,1 表示以 u 为根的子树中 u 在最大独立集中最多可以选多少点。

接下来考虑转移:

对于 fu,0 ,因为 u 不选,所以 u 的儿子可选可不选,则 fu,0=max(fv,0,fv,1)

对于 fu,1 ,因为 u 要选,所以 u 的儿子一定不能选,则 fu,1=1+fv,0

则最后的答案为 max(froot,0,froot,1)

int f[MAXN][2];
void Dfs(int u,int fa)
{
	f[u][0]=0;f[u][1]=1;
	for(int v:G[u])
	{
		if(v==fa) continue;
		Dfs(v,u);
		f[u][0]+=max(f[v][0],f[v][1]);
		f[u][1]+=f[v][0];
	}
}
  • 最小支配集

问题:

给定一棵 n 个点的树,从 n 个点中选取尽量少的点,使得任意一个不在支配集中的点都和一个在支配集中的点有连边。

分析:

我们设 fu,0 表示 u 在支配集中至少要选几个点,简称被自己支配。

fu,1 表示 u 不在支配集中,而 u 的儿子在支配集中至少要选几个点,简称被儿子支配。

fu,2 表示 u 不在支配集中,而 u 的父亲在支配集中至少要选几个点,简称被父亲支配。

接下来考虑转移:

对于 fu,0 ,因为 u 选了,那么 u 的儿子可选可不选,所以 fu,0=1+min(fv,0,fv,1,fv,2)

对于 fu,1 ,因为 u 不选,而至少要有一个 u 的儿子要选,所以我们枚举选的儿子 vi ,设 xu 的儿子数,则其余的儿子为 vj(1ix , ij) ,则 fu,1=fvi,0+min(fvj,0,fvj,1)

对于 fu,2 ,因为 u 靠了 u 的父亲支配,则 u 的儿子只能靠自己或者自己的儿子。则 fu,2=min(fv,0,fv,1)

则最后的答案为 min(froot,0,froot,1)

void Dfs(int u,int fa)
{
	int sum=0;
	for(int v:G[u])
	{
		if(v==fa) continue;
		Dfs(v,u);
		sum+=min(f[v][0],f[v][1]);
	}
	f[u][0]=1;f[u][1]=INF;f[u][2]=0;
	for(int v:G[u])
	{
		if(v==fa) continue;
		f[u][0]+=min(min(f[v][0],f[v][1]),f[v][2]);
		f[u][1]=min(f[u][1],sum-min(f[v][0],f[v][1])+f[v][0]);
		f[u][2]+=min(f[v][0],f[v][1]);
	}
}
posted @   zhln  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示