码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-04-06 15:18:56      阅读:56      评论:0      收藏:0      [点我收藏+]

标签:pac   树形dp   als   包含   ack   push   oid   相同   using   

给一棵 \(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\to q} \min(f[q][0]-1,f[q][1]) \f[p][1] = \sum_{p\to 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

标签:pac   树形dp   als   包含   ack   push   oid   相同   using   

原文地址:https://www.cnblogs.com/mollnn/p/12642065.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!