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

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 730  Solved: 485
    [Submit][Status][Discuss]

    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

    先随便选一个根。

    dp[x][0/1]表示以x为根的子树中,x节点被染成黑/白色,并且这棵子树中的叶子都被满足的最小染色数。

    然后发现如果x的一个儿子和它同色,那么儿子是不必要染色的(既然有的叶子到根的第一个有色节点是x的儿子,

    那么如果把x的儿子替换成x也是ojbk的)

    但是异色肯定是要染的。
    所以dp[x][i]=∑min(dp[son][i]-1,dp[son][i^1])。
     
    然后惊奇的发现换根对答案并没有什么影响,加入把root的某个儿子son旋上来,那么原来到son的现在还是到son,
    son子树外的还是到root(或者root的某个异色的儿子),所以O(N)随便选个不是叶子的当根算一次就好了。
     
    /**************************************************************
        Problem: 1304
        User: JYYHH
        Language: C++
        Result: Accepted
        Time:60 ms
        Memory:1660 kb
    ****************************************************************/
     
    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 10005
    #define pb push_back
    using namespace std;
    vector<int> g[maxn];
    int dp[maxn][2],col[maxn];
    int n,m;
     
    void dfs(int x,int fa){
        if(x<=m) return;
        int to; dp[x][0]=dp[x][1]=1;
        for(int i=g[x].size()-1;i>=0;i--){
            to=g[x][i];
            if(to==fa) continue;
            dfs(to,x);
             
            dp[x][0]+=min(dp[to][1],dp[to][0]-1);
            dp[x][1]+=min(dp[to][0],dp[to][1]-1);
        }
    }
     
    int main(){
        memset(dp,0x3f,sizeof(dp));
         
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d",col+i);
            dp[i][col[i]]=1;
        }
         
        int uu,vv;
        for(int i=1;i<n;i++){
            scanf("%d%d",&uu,&vv);
            g[uu].pb(vv),g[vv].pb(uu);
        }
         
        dfs(n,n);
        printf("%d
    ",min(dp[n][0],dp[n][1]));
        return 0;
    }
    
  • 相关阅读:
    Alpha阶段项目复审
    复审与事后分析
    测试与发布(Alpha版本)
    第七天
    第六天
    团队作业第4周——项目冲刺
    第一天
    第二天
    第四天
    第五天
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8300906.html
Copyright © 2011-2022 走看看