[CQOI2009] 叶子的染色 - 树形dp

Posted mollnn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2009] 叶子的染色 - 树形dp相关的知识,希望对你有一定的参考价值。

给一棵 (m) 个结点的无根树,你可以选择一个度数大于 (1) 的结点作为根,然后给一些结点着以黑色或白色。方案应保证根结点到每个叶子的简单路径上都至少包含一个有色结点。 对于每个叶结点 (u) ,定义 (c[u]) 为从根结点从 (u) 的简单路径上最后一个有色结点的颜色。给出每个 (c[u]) 的值,设计着色方案,使得着色结点的个数尽量少。

Solution

选择任意一个点为根,答案都是相同的

随便选一个点为根,然后设 (f[i][0/1]) 表示将 (i) 染色为 (0/1),且子树内都完成了染色的最小代价

对于一个叶子结点,若颜色为 (0),则令 (f[p][0]=1,f[p][1]=infty),反之亦然

对于一个非叶子结点,令 (f[p][0]=f[p][1]=1)

转移方程

[f[p][0] = sum_{p o q} min(f[q][0]-1,f[q][1]) f[p][1] = sum_{p o q} min(f[q][1]-1,f[q][0]) ]

#include <bits/stdc++.h>
using namespace std;

const int N = 10005;

vector <int> g[N];
int n,m,c[N],t1,t2,d[N],vis[N],f[N][2];

void dfs(int p) {
    vis[p]=1;
    for(int q:g[p]) {
        if(vis[q]==0) {
            dfs(q);
            f[p][0]+=min(f[q][0]-1,f[q][1]);
            f[p][1]+=min(f[q][1]-1,f[q][0]);
        }
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=m;i++) cin>>c[i];
    for(int i=1;i<n;i++) {
        cin>>t1>>t2;
        g[t1].push_back(t2);
        g[t2].push_back(t1);
    }
    for(int i=1;i<=m;i++) {
        f[i][c[i]]=1;
        f[i][c[i]^1]=1e9;
    }
    for(int i=m+1;i<=n;i++) {
        f[i][0]=f[i][1]=1;
    }
    dfs(m+1);
    cout<<min(f[m+1][0],f[m+1][1]);
}

以上是关于[CQOI2009] 叶子的染色 - 树形dp的主要内容,如果未能解决你的问题,请参考以下文章

[CQOI2009] 叶子的染色 - 树形dp

bzoj1304: [CQOI2009]叶子的染色(树形DP)

bzoj1304[CQOI2009]叶子的染色 树形dp

CQOI2009 叶子的染色

[CQOI2009]叶子的染色

BZOJ 1304: [CQOI2009]叶子的染色