zoukankan      html  css  js  c++  java
  • 一本通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 的值。

    接下来 m1 行每行两个整数 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
  • 相关阅读:
    Codeforces Beta Round #6 (Div. 2 Only)
    Codeforces Beta Round #5
    Codeforces Beta Round #4 (Div. 2 Only)
    Codeforces Beta Round #3
    Codeforces Beta Round #2
    Codeforces Beta Round #1
    HDU 4020 Ads Proposal
    SRM 615 DIV1 500
    求1+2+……+n(位运算)
    好好加油!
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10357981.html
Copyright © 2011-2022 走看看