引子
树形DP是一种基于树结构的动态规划算法,利用树的递归特性进行状态转移。根据兄弟节点间的约束关系,可分为两种类型:
- 无相互约束型:兄弟节点的决策互不影响
- 有相互约束型:兄弟节点的决策相互制约
P3155 [CQOI2009] 叶子的染色
1.状态
dp[i][0/1]表示以i为根的子树且点i染色为0或1,且子树内叶子合法的最少染色数。
2.答案
min(dp[m][0],dp[m][1])
3.转移
考虑cur->nxt父子关系
cpp
dfs(nxt,cur);
dp[cur][0]+=min(dp[nxt][0]-1,dp[nxt][1]);
4.code实现
cpp
#include<bits/stdc++.h>
using namespace std;
int m,n,c[5025],dp[10005][2];
vector<int> E[10005];
void dfs(int x,int fa){
dp[x][0]=dp[x][1]=1;
if(x<=n){
dp[x][1-c[x]]=1e9;
}
for(int i=0;i<E[x].size();i++){
int v=E[x][i];
if(v==fa)continue;
dfs(v,x);
dp[x][0]+=min(dp[v][0]-1,dp[v][1]);
dp[x][1]+=min(dp[v][1]-1,dp[v][0]);
}
}
int main(){
cin>>m>>n;
for(int i=1;i<=n;i++){
cin>>c[i];
}
for(int i=1;i<m;i++){
int u,v;
cin>>u>>v;
E[u].push_back(v);
E[v].push_back(u);
}
dfs(m,0);
cout<<min(dp[m][0],dp[m][1]);
return 0;
}