树形 DP 问题
树形 问题
-
最小点覆盖
问题:
给定一颗有 个点的有根树,从这 个点中选出尽量少的点,使得所有边都与取出来的点相连。
分析:
考虑一条边,它两端的节点必定有一个在所选点集中,可以考虑 :
设 表示以 为根的子树中, 不在点覆盖集中所需要选取的最小点数; 表示以 为根的子树中, 在点覆盖集中所需要选取的最小点数。
接下来考虑转移 (其中 为 的儿子):
对于 ,因为 不选取,则 的儿子一定要取,所以
对于 , 因为 要选取,则 的儿子可选可不选,所以
设根节点为 ,则最后答案为
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]);
}
}
-
最大独立集
问题:
给定一棵有 个点的树,从 个点中选出尽量多的点,使得两两之间没有连边。
分析:
同上,考虑一条边,它两端的点不能被同时选取,那么考虑 :
设 表示以 为根的子树中 不在最大独立集中最多可以选多少点, 表示以 为根的子树中 在最大独立集中最多可以选多少点。
接下来考虑转移:
对于 ,因为 不选,所以 的儿子可选可不选,则
对于 ,因为 要选,所以 的儿子一定不能选,则
则最后的答案为
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];
}
}
-
最小支配集
问题:
给定一棵 个点的树,从 个点中选取尽量少的点,使得任意一个不在支配集中的点都和一个在支配集中的点有连边。
分析:
我们设 表示 在支配集中至少要选几个点,简称被自己支配。
表示 不在支配集中,而 的儿子在支配集中至少要选几个点,简称被儿子支配。
表示 不在支配集中,而 的父亲在支配集中至少要选几个点,简称被父亲支配。
接下来考虑转移:
对于 ,因为 选了,那么 的儿子可选可不选,所以
对于 ,因为 不选,而至少要有一个 的儿子要选,所以我们枚举选的儿子 ,设 为 的儿子数,则其余的儿子为 ,则
对于 ,因为 靠了 的父亲支配,则 的儿子只能靠自己或者自己的儿子。则
则最后的答案为
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]);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】