[CQOI2009]叶子的染色

题目描述

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

输入格式

第一行包含两个正整数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 有边相连。

输出格式

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


f[x][0/1]表示x节点染0/1颜色的最小值

#include<bits/stdc++.h> 
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
}


const int maxn=20005,maxm=40005; 
int n,m,k,col[maxn],hd[maxn],f[maxn][2];
struct node{
    int to,nt;
}e[maxm];

inline void add(int x,int y)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
}

inline void dfs(int x,int fa)
{
    for(int i=hd[x];i;i=e[i].nt) 
    {
        int v=e[i].to;
        if(v==fa)continue;
        dfs(v,x);
        //同色路相减 
        f[x][0]+=min(f[v][0]-1,f[v][1]);
        f[x][1]+=min(f[v][0],f[v][1]-1);
    }
}

int main()
{
    freopen("in.txt","r",stdin);
    int x,y,z;
    rd(n);rd(m);
    inc(i,1,m)
    {
        rd(col[i]); 
        f[i][col[i]]=1;
        f[i][col[i]^1]=2147483645;
    }
    
    inc(i,m+1,n)f[i][1]=f[i][0]=1;//初始化 
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y);
    }
    
    dfs(n,n);//只要是非叶节点作根都没有什么太大的问题
    //因为叶节点会强制不选某个颜色 
    printf("%d",min(f[n][1],f[n][0]));
    re 0;
}

 

 

 

posted @ 2019-08-30 09:36  凉如水  阅读(159)  评论(0编辑  收藏  举报