zoukankan      html  css  js  c++  java
  • [CQOI2009] 叶子的染色

    给一棵 (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]);
    }
    
    
  • 相关阅读:
    DFS复习
    二叉搜索树专题
    二叉树路径问题
    二叉树LCA--leetcode236题
    二叉树创建与前、中、后序遍历
    leetCode--n数之和--哈希表/双指针
    leetCode--单词接龙--BFS
    vue-router简单实现
    Promise的简单实现
    闭包&作用域链&let
  • 原文地址:https://www.cnblogs.com/mollnn/p/12642065.html
Copyright © 2011-2022 走看看