码迷,mamicode.com
首页 > 其他好文 > 详细

一本通1583叶子的染色

时间:2019-02-09 22:50:55      阅读:298      评论:0      收藏:0      [点我收藏+]

标签:splay   \n   getchar   inpu   hide   list   图片   ons   方案   

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(\n);
    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叶子的染色

标签:splay   \n   getchar   inpu   hide   list   图片   ons   方案   

原文地址:https://www.cnblogs.com/gaojunonly1/p/10357981.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!