树形dp刷题
title: 树形dp刷题
categories:
- ICPC
tags:
- null
abbrlink: ‘1e240034’
date: 2023-02-24 00:00:00
专题班树型dp练习https://ac.nowcoder.com/acm/contest/28260#question
原问题求树上的最大独立集
Solution:仔细读题,一开始以为每次选择的地点是连续的,导致求成最大深度了。实际上是最大独立集。
debug:对于每个儿子的贡献需要累加,叶子节点需要赋初值。
vector<int>e[N];
int dp[N][2];
void dfs(int u,int fa){
dp[u][1]=1;//叶节点赋值和每个点本身贡献
for(auto v:e[u]){
if(v==fa)continue;
dfs(v,u);
dp[u][1]+=dp[v][0];//有多个叶子,应该是+=,不是+
dp[u][0]+=max(dp[v][1],dp[v][0]);
}
}
void solve(){
int rt;cin>>n>>rt;
for(int i=1;i<=n-1;i++){
int u,v;cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
// memset(dp,0x3f,sizeof dp);
dfs(rt,0);
int ans=dp[rt][1];
//
cout<<ans<<endl;
}
伪装成树上dp的树上贪心
题意:给定一棵树,树上每个节点都有一个权值k[i],表示如果染色这个点到根的树链上能免费染色距离i不超过k[i]的点,求最少染色次数
Solution:贪心还是需要慢慢分析,中间更新最大值也算dp(bushi).
由于每个点都只会被他子树以内的点染色,我们每次维护它的子树除了它能染色的最大高度。如果为0,说明之前的贪心策略无法满足,需要多花费一次染色次数,
考虑选择能贡献最大的点,这个值也需要一直维护更新,具体来说就是u这个点k值和max(v的k值)-1去比较。
在花费一次染色机会的时候,用k去维护f
//看似树上dp,其实树上贪心
//由于本题染色是受到子节点影响
//从下向上思考问题,如果当前所有子节点上传的值都无法染色该点,我们
//只能考虑在之前没被染色的值里选一个最大的,所以我们需要维护这个
int k[N];
int f[N];
//k[i]表示以i为子树的所有点所能向上影响最大值
//f[i]表示当前实际方案中,i的子树最多能向上跳到哪
int cnt=0;
vector<int>e[N];
void dfs(int x){
for(auto v:e[x]){
dfs(v);
k[x]=max(k[x],k[v]-1);
f[x]=max(f[x],f[v]-1);
}
if(f[x]==0){
//说明当前这个点在当前方案下已经无法染色了
//做出改变:再选一个点染色,在所有备选的点中选取最大值
f[x]=k[x];
cnt++;
}
}
void solve(){
cin>>n;
for(int i=2;i<=n;i++){
int x;cin>>x;
e[x].push_back(i);
}
for(int i=1;i<=n;i++)cin>>k[i];
dfs(1);
cout<<cnt<<endl;
}
https://www.nowcoder.com/discuss/353157393250983936?sourceSSR=search
专题班树型dp例题https://ac.nowcoder.com/acm/contest/28258
求树的重心
Solution:只需要枚举每个点,比较重儿子大小和父节点以上的大小,比较出最大连通块大小的最小值
int sz[N];
int son[N];
vector<int>e[N];
void dfs(int u,int fa){
sz[u]=1;
for(auto v:e[u]){
if(v==fa)continue;
dfs(v,u);
if(son[u]<sz[v])son[u]=sz[v];
sz[u]+=sz[v];
}
}
void solve(){
while(cin>>n){
for(int i=1;i<=n;i++)e[i].clear();
fill(sz,sz+n+1,0);
for(int i=1;i<=n-1;i++){
int u,v;cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
int ans=1e9;int pos=0;
for(int i=1;i<=n;i++){
int tmp=max(son[i],n-sz[i]);
if(ans>tmp){
ans=tmp;
pos=i;
}
}
cout<<pos<<" "<<ans<<endl;
}
}
树上问题选讲 - hztmax0 - 博客园 (cnblogs.com)
222222222222222树形背包总结 - lnzwz - 博客园 (cnblogs.com)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 爱飞鱼的blog!