bzoj千题计划233:bzoj 1304: [CQOI2009]叶子的染色

http://www.lydsy.com/JudgeOnline/problem.php?id=1304

结论1:根节点一定染色

如果根节点没有染色,选择其子节点的一个颜色,那么所有这个颜色的子节点都不用染色。答案不会更差。

结论2:相邻节点不会染同一种颜色

将深度更大的那个有色节点变成无色仍然满足要求

结论3;任意一个非叶子节点做根,对答案都没有影响。

考虑将原根节点的一个自己点换成根,原来到根最近的颜色节点不变

所以,任取一个非叶子节点做根

dp[x][0/1]表示x染黑/白,使其子树内叶子节点满足要求的最少颜色节点数

dp[x][0]=(Σ min(dp[t][0]-1,dp[t][1]) )+1

dp[x][1]=(Σ min(dp[t][1]-1,dp[t][0]) )+1

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 10001

int col[N];

int front[N],nxt[N<<1],to[N<<1],tot;

int dp[N][2];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); }
}

void add(int u,int v)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

void dfs(int x,int y)
{
    if(col[x]!=-1)
    {
        dp[x][col[x]]=1;
        dp[x][col[x]^1]=1e7;
        return;
    }
    for(int i=front[x];i;i=nxt[i])
        if(to[i]!=y)
        {
            dfs(to[i],x);
            dp[x][0]+=min(dp[to[i]][0]-1,dp[to[i]][1]);
            dp[x][1]+=min(dp[to[i]][1]-1,dp[to[i]][0]);
        }
    dp[x][0]++;
    dp[x][1]++;
}

int main()
{
    int n,m;
    read(n); read(m);
    memset(col,-1,sizeof(col));
    for(int i=1;i<=m;++i)  read(col[i]);
    int u,v;
    for(int i=1;i<n;++i)
    {
        read(u); read(v);
        add(u,v);
    }
    dfs(n,0);
    printf("%d",min(dp[n][0],dp[n][1]));
}

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8443382.html

时间: 2024-07-30 07:37:43

bzoj千题计划233:bzoj 1304: [CQOI2009]叶子的染色的相关文章

bzoj千题计划130:bzoj1305: [CQOI2009]dance跳舞

http://www.lydsy.com/JudgeOnline/problem.php?id=1305 每个人拆为喜欢(yes)和不喜欢(no)两个点 二分答案 1.每两个人之间只能跳一次 喜欢则 男yes i 向 女yes j 连流量为1的边 不喜欢则 男no i 向 女no j 连流量为1的边 2.最多与k个不喜欢的人跳 男yes i 向 男no i 连流量为 k的边 女no j 向 女yes j 连流量为k 的边 3. 源点向 男yes i 连流量mid 的边 女yes j 向汇点连流量

bzoj千题计划175:bzoj1303: [CQOI2009]中位数图

http://www.lydsy.com/JudgeOnline/problem.php?id=1303 令c[i]表示前i个数中,比d大的数与比d小的数的差,那么如果c[l]=c[r],则[l+1,r]满足条件 #include<cstdio> #include<iostream> using namespace std; const int N=1e7; int c[N*2],g[N]; void read(int &x) { x=0; char c=getchar()

1304: [CQOI2009]叶子的染色 - BZOJ

Description给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含一个有色结点(哪怕是这个叶子本身). 对于每个叶结点u,定义c[u]为从u到根结点的简单路径上最后一个(应该是最深的那个吧)有色结点的颜色.给出每个c[u]的值,设计着色方案,使得着色结点的个数尽量少.Input第一行包含两个正整数m, n,其中n是叶子的个数,m是结点总数.结点编号为1,2,-,m,

BZOJ 1304: [CQOI2009]叶子的染色

1304: [CQOI2009]叶子的染色 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 566  Solved: 358[Submit][Status][Discuss] Description 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含一个有色结点(哪怕是这个叶子本身). 对于每个叶结点u,定义c[u]为从根结

bzoj千题计划185:bzoj1260: [CQOI2007]涂色paint

http://www.lydsy.com/JudgeOnline/problem.php?id=1260 区间DP模型 dp[l][r] 表示涂完区间[l,r]所需的最少次数 从小到大们枚举区间[l,r] 如果col[l]==col[r] dp[l][r]=min(dp[l+1][r],dp[l][r-1],dp[l+1][r-1]+1) 否则 dp[l][r]=min(dp[l][k]+dp[k+1][r]) 我还是辣鸡啊~~~~(>_<)~~~~,这种题都不能秒 #include<c

bzoj千题计划227:bzo1486: [HNOI2009]最小圈j

http://www.lydsy.com/JudgeOnline/problem.php?id=1486 二分答案 dfs版spfa判负环 #include<queue> #include<cstdio> #include<cstring> #include<iostream> #define N 3001 #define M 10001 using namespace std; int n; int tot,front[N],nxt[M],to[M]; d

bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len [i] 表示以i结尾的最长不下降子序列的长度 pre_sum[i] 表示对应长度下的方案数 suf_len[i] 表示以i开头的最长不下降子序列长度 suf_sum[i] 表示对应长度下的方案数 若已有了这4个数组 设最长上升子序列长度=mx 那么 如果pre_len[i]+suf_len[i] -

bzoj千题计划304:bzoj3676: [Apio2014]回文串

https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 300001 char ss[N]; int s[N]; int tot=1,last; int fail[N],len

bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include<cstdio> #include<cstring> #include<iostream> #define L 100001 typedef unsigned long long ULL; using namespace std; char s[L+4]; int tot,root