一本通1583叶子的染色

Posted gaojunonly1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一本通1583叶子的染色相关的知识,希望对你有一定的参考价值。

1583:叶子的染色

时间限制: 1000 ms         内存限制: 524288 KB

题目描述

原题来自:CQOI 2009

给一棵有 m 个节点的无根树,你可以选择一个度数大于 1 的节点作为根,然后给一些节点(根、内部节点、叶子均可)着以黑色或白色。你的着色方案应保证根节点到各叶子节点的简单路径上都包含一个有色节点,哪怕是叶子本身。

对于每个叶子节点 u,定义 cu? 为从根节点到 u 的简单路径上最后一个有色节点的颜色。给出每个 cu? 的值,设计着色方案使得着色节点的个数尽量少。

输入格式

第一行包括两个数 m,n,依次表示节点总数和叶子个数,节点编号依次为 1 至 m。

接下来 n 行每行一个 0 或 1 的数,其中 0 表示黑色,1 表示白色,依次为 c1?,c2?,?,cn? 的值。

接下来 m?1 行每行两个整数 a,b,表示节点 a 与 b 有边相连。

输出格式

输出仅一个数,表示着色节点数的最小值。

样例

样例输入

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

样例输出

2

数据范围与提示

数据1
234567
8
910
m
10 50 100 200 400 1000 4000 8000 10000 10000
n
5
23 50 98 197 498 2044 4004 5021 4996
 

sol:看上去好复杂的样子,dp[x][0,1]表示在x的子树中x选择颜色0,1时的最小代价,因为在这个子树中根节点放个颜色一定是最优的(不放心的话可以写一下dp[x][2]表示x没有颜色时子树的最小代价),然后暴力转移下去,遇到叶子就弹出

 

技术图片
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
    int s=0;
    bool f=0;
    char ch= ;
    while(!isdigit(ch))
    {
        f|=(ch==-);
        ch=getchar();
    }
    while(isdigit(ch))
    {
        s=(s<<3)+(s<<1)+(ch^48);
        ch=getchar();
    }
    return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(long long x)
{
    if(x<0)
    {
        putchar(-);
        x=-x;
    }
    if(x<10)
    {
        putchar(x+0);
        return;
    }
    write(x/10);
    putchar((x%10)+0);
    return;
}
inline void writeln(long long x)
{
    write(x);
    putchar(
);
    return;
}
#define W(x) write(x),putchar(‘ ‘)
#define Wl(x) writeln(x)
const int N=10005,B=5025,M=20005,inf=0x3f3f3f3f;
int n,m,Cor[B];
struct Tree
{
    int tot,Next[M],to[M],head[N];
    inline void add(int x,int y)
    {
        Next[++tot]=head[x];
        to[tot]=y;
        head[x]=tot;
        return;
    }
    long long dp[N][2];
    inline void dfs(int x,int fa)
    {
        dp[x][0]=dp[x][1]=1;
        if(x<=m)
        {
            dp[x][Cor[x]^1]=inf;
            return;
        }
        int i;
        for(i=head[x];i;i=Next[i]) if(to[i]!=fa)
        {
            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]);
        }
        return;
    }
    inline void Solve()
    {
        dfs(n,0);
        Wl(min(dp[n][0],dp[n][1]));
        return;
    }
    inline void Init()
    {
        tot=0;
        memset(head,0,sizeof head);
        return;
    }
}T;
int main()
{
//    freopen("9.in","r",stdin);
    int i;
    T.Init();
    R(n); R(m);
    for(i=1;i<=m;i++) R(Cor[i]);
    for(i=1;i<n;i++)
    {
        int x=read(),y=read();
        T.add(x,y); T.add(y,x);
    }
    T.Solve();
    return 0;
}
/*
input
5 3
0
1
0
1 4
2 5
4 5
3 5
output
2
*/
View Code

 

 

 








以上是关于一本通1583叶子的染色的主要内容,如果未能解决你的问题,请参考以下文章

一本通 高手训练 1781 死亡之树 状态压缩dp

CQOI2009 叶子的染色

P3155 [CQOI2009]叶子的染色

叶子的染色

[CQOI2009]叶子的染色

BZOJ1304[CQOI2009]叶子的染色 树形DP