树形 DP 问题
树形 \(dp\) 问题
- 
最小点覆盖
问题:
给定一颗有 \(n\) 个点的有根树,从这 \(n\) 个点中选出尽量少的点,使得所有边都与取出来的点相连。
分析:
考虑一条边,它两端的节点必定有一个在所选点集中,可以考虑 \(dp\) :
设 \(f_{u,0}\) 表示以 \(u\) 为根的子树中, \(u\) 不在点覆盖集中所需要选取的最小点数; \(f_{u,1}\) 表示以 \(u\) 为根的子树中, \(u\) 在点覆盖集中所需要选取的最小点数。
接下来考虑转移 (其中 \(v\) 为 \(u\) 的儿子):
对于 \(f_{u,0}\) ,因为 \(u\) 不选取,则 \(u\) 的儿子一定要取,所以 \(f_{u,0}=\sum f_{v,1}\)
对于 \(f_{u,1}\) , 因为 \(u\) 要选取,则 \(u\) 的儿子可选可不选,所以 \(f_{u,1} = 1+\sum min(f_{v,0},f_{v,1})\)
设根节点为 \(root\) ,则最后答案为 \(min(f_{root,0},f_{root,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\) :
设 \(f_{u,0}\) 表示以 \(u\) 为根的子树中 \(u\) 不在最大独立集中最多可以选多少点, \(f_{u,1}\) 表示以 \(u\) 为根的子树中 \(u\) 在最大独立集中最多可以选多少点。
接下来考虑转移:
对于 \(f_{u,0}\) ,因为 \(u\) 不选,所以 \(u\) 的儿子可选可不选,则 \(f_{u,0}=\sum max(f_{v,0},f_{v,1})\)
对于 \(f_{u,1}\) ,因为 \(u\) 要选,所以 \(u\) 的儿子一定不能选,则 \(f_{u,1}=1+\sum f_{v,0}\)
则最后的答案为 \(max(f_{root,0},f_{root,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\) 个点中选取尽量少的点,使得任意一个不在支配集中的点都和一个在支配集中的点有连边。
分析:
我们设 \(f_{u,0}\) 表示 \(u\) 在支配集中至少要选几个点,简称被自己支配。
\(f_{u,1}\) 表示 \(u\) 不在支配集中,而 \(u\) 的儿子在支配集中至少要选几个点,简称被儿子支配。
\(f_{u,2}\) 表示 \(u\) 不在支配集中,而 \(u\) 的父亲在支配集中至少要选几个点,简称被父亲支配。
接下来考虑转移:
对于 \(f_{u,0}\) ,因为 \(u\) 选了,那么 \(u\) 的儿子可选可不选,所以 \(f_{u,0}=1+\sum min(f_{v,0},f_{v,1},f_{v,2})\)
对于 \(f_{u,1}\) ,因为 \(u\) 不选,而至少要有一个 \(u\) 的儿子要选,所以我们枚举选的儿子 \(v_i\) ,设 \(x\) 为 \(u\) 的儿子数,则其余的儿子为 \(v_j(1 \leq i \leq x\ ,\ i \not= j)\) ,则 \(f_{u,1}=f_{v_i,0}+\sum min(f_{v_j,0},f_{v_j,1})\)
对于 \(f_{u,2}\) ,因为 \(u\) 靠了 \(u\) 的父亲支配,则 \(u\) 的儿子只能靠自己或者自己的儿子。则 \(f_{u,2}=\sum min(f_{v,0},f_{v,1})\)
则最后的答案为 \(min(f_{root,0},f_{root,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]);
	}
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号