• BZOJ1304: [CQOI2009]叶子的染色 树形dp


    Description

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

    Input

    第一行包含两个正整数m, n,其中n是叶子的个数,m是结点总数。结点编号为1,2,…,m,其中编号1,2,… ,n是叶子。以下n行每行一个0或1的整数(0表示黑色,1表示白色),依次为c[1],c[2],…,c[n]。以下m-1行每行两个整数a,b(1<=a < b <= m),表示结点a和b 有边相连。

    Output

    仅一个数,即着色结点数的最小值。

    Sample Input

    5 3
    0
    1
    0
    1 4
    2 5
    4 5
    3 5

    Sample Output

    2

    HINT

    M<=10000


    N<=5021

    Solution

    这题只要知道结论就很好做了

    然而是神仙结论:选择任何一个点为根对答案没有任何影响(不会证)

    所以直接随便选个点当根然后树形dp就可以了

    $f[u][0]$和$f[u][1]$表示$u$的子树中,最后一个点想要得到一个白色/黑色的祖先,的最小代价

    #include <bits/stdc++.h>
    
    using namespace std ;
    
    #define N 100010
    #define inf 0x3f3f3f3f
    
    int n , m ;
    int c[ N ] ;
    int f[ N ][ 2 ] ;
    int head[ N ] , cnt ;
    int fa[ N ] ;
    struct node {
        int to , nxt ;
    } e[ N ] ;
    
    void ins( int u , int v ) {
        e[ ++ cnt ].to = v ;
        e[ cnt ].nxt = head[ u ] ; 
        head[ u ] = cnt ;
    }
    
    void dfs( int u ) {
        if( u <= n ) {
            f[ u ][ c[ u ] ] = 0 ;
            f[ u ][ c[ u ] ^ 1 ] = inf ; 
        }
        for( int i = head[ u ] ; i ; i = e[ i ].nxt ) {
            if( e[ i ].to == fa[ u ] ) continue ;
            fa[ e[ i ].to ] = u ;
            dfs( e[ i ].to ) ;
            f[ u ][ 0 ] += min( f[ e[ i ].to ][ 0 ] , f[ e[ i ].to ][ 1 ] + 1 ) ;
            f[ u ][ 1 ] += min( f[ e[ i ].to ][ 0 ] + 1 , f[ e[ i ].to ][ 1 ] ) ;
        }
    }
    
    int main() {
        scanf( "%d%d" , &m , &n ) ;
        for( int i = 1 ; i <= n ; i ++ ) {
            scanf( "%d" , &c[ i ] ) ;
        }
        for( int i = 1 , a , b ; i < m ; i ++ ) {
            scanf( "%d%d" , &a , &b ) ;
            ins( a , b ) ; ins( b , a ) ;
        }
        dfs( m ) ;
        printf( "%d
    " , min( f[ m ][ 0 ] , f[ m ][ 1 ] ) + 1 ) ;
        return 0 ;
    }
  • 相关阅读:
    FPGA实现USB2.0同步读数据传输且用chipscop抓取波形(3)
    FPGA实现对USB2.0的同步数据传输及USB2.0固件配置(2)
    通过MATLAB实现图像数据转换成.bin格式在USB2.0上传输(1)
    【转】ssh免密码登录的原理
    【转】ssh登录原理以及ssh免密码登陆
    Windows与VMware中的CentOS系统互通访问
    第十一章 条件逻辑
    第十章 再谈连接
    第九章 子查询
    第八章 分组和聚集
  • 原文地址:https://www.cnblogs.com/henry-1202/p/BZOJ1304.html
Copyright © 2020-2023  润新知