又是一道优美的dp

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

2

HINT

M<=10000

N<=5021


题目分析

这题的限制有些诡异,并且长得非常不像dp。仿佛我们需要三个状态$f[i][0/1/2]$来表示当前涂色状态,而且这样转移起来甚是麻烦。

但是细细一想,若一个点$node$有众多子节点,那就意味着有众多的叶子节点。而每一个叶子节点都是要上色的,况且上的色非黑即白就两种。

那么不论$node$子树内白多黑多,$node$这个节点当然要承担起父节点的责任,涂成一种颜色,这样肯定是不会更差的。

于是只有两个状态的树形dp就不难想到也不难打出了。

 /**************************************************************
    Problem: 1304
    User: AntiQuality
    Language: C++
    Result: Accepted
    Time:20 ms
    Memory:1600 kb
****************************************************************/
 
#include<bits/stdc++.h>
const int maxn = ;
const int INF = 2e9;
 
int n,m,c[maxn];
int f[maxn][];
int edgeTot,edges[maxn<<],nxt[maxn<<],head[maxn];
 
int read()
{
    char ch = getchar();
    int num = ;
    bool fl = ;
    for (; !isdigit(ch); ch = getchar())
        if (ch=='-') fl = ;
    for (; isdigit(ch); ch = getchar())
        num = (num<<)+(num<<)+ch-;
    if (fl) num = -num;
    return num;
}
void addedge(int u, int v)
{
    edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
    edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
}
void dp(int now, int fa)
{
    if (now <= n){
        f[now][c[now]] = , f[now][-c[now]] = INF;
        return;
    }
    f[now][] = , f[now][] = ;
    for (int i=head[now]; i!=-; i=nxt[i])
    {
        int v = edges[i];
        if (v!=fa){
            dp(v, now);
            f[now][] += std::min(f[v][], f[v][]-);  //可能这里为什么f[v][1]不加1,而是f[v][0]减1会有点疑问
            f[now][] += std::min(f[v][], f[v][]-);  //f[now][]=1是每次dp时先确定好了的,这样可以避免重复计算
        }                             //手推一下就好了
    }
}
int main()
{
    memset(head, -, sizeof head);
    m = read(), n = read();
    for (int i=; i<=n; i++) c[i] = read();
    for (int i=; i<m; i++) addedge(read(), read());
    dp(m, );
    printf("%d\n",std::min(f[m][], f[m][]));
    return ;
}

END

【树形dp】bzoj1304: [CQOI2009]叶子的染色的更多相关文章

  1. BZOJ1304 CQOI2009 叶子的染色 【树形DP】

    BZOJ1304 CQOI2009 叶子的染色 Description 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方 ...

  2. BZOJ1304: [CQOI2009]叶子的染色 树形dp

    Description 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含 ...

  3. BZOJ1304: [CQOI2009]叶子的染色

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1304 树形dp. 可以发现其实根选在哪里都是没有问题的. f[u][0],f[u][1],f[ ...

  4. BZOJ1304 CQOI2009叶子的染色(树形dp)

    令f[i]表示i子树内最少染色次数,加上012状态分别表示该子树内叶节点已均被满足.存在黑色叶节点未被满足.存在白色叶节点未被满足,考虑i节点涂色情况即可转移.事实上贪心也可以. #include&l ...

  5. BZOJ_1304_[CQOI2009]叶子的染色_树形DP

    BZOJ_1304_[CQOI2009]叶子的染色_树形DP Description 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白 ...

  6. 【BZOJ1304】[CQOI2009]叶子的染色(动态规划)

    [BZOJ1304][CQOI2009]叶子的染色(动态规划) 题面 BZOJ 洛谷 题解 很简单. 设\(f[i][0/1/2]\)表示以\(i\)为根的子树中,还有颜色为\(0/1/2\)(\(2 ...

  7. BZOJ 1304: [CQOI2009]叶子的染色

    1304: [CQOI2009]叶子的染色 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 566  Solved: 358[Submit][Statu ...

  8. 洛谷 P3155 [CQOI2009]叶子的染色 解题报告

    P3155 [CQOI2009]叶子的染色 题目描述 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到 ...

  9. P3155 [CQOI2009]叶子的染色

    P3155 [CQOI2009]叶子的染色 题目描述 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部结点和叶子均可)着以黑色或白色.你的着色方案应该保证根结点到 ...

随机推荐

  1. ssh 下载文件以及上传文件到服务器

    https://blog.csdn.net/jackghq/article/details/64124062 scp john@192.168.1.100:~/Desktop/MHN_error_so ...

  2. 洛谷 P1908 逆序对(树状数组解法)

    归并排序解法:https://www.cnblogs.com/lipeiyi520/p/10356882.html 题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不 ...

  3. nutz 使用beetl

    src目录或src同级的其他目录(比如conf)下创建 beetl.properties文件,文件内容如下 (maven项目)在resources目录下创建 RESOURCE_LOADER=org.b ...

  4. 洛谷P2470||bzoj1068 [SCOI2007]压缩

    bzoj1068 洛谷P2470 区间dp入门题?只要注意到每个M“管辖”的区间互不相交即可 错误记录:有点小坑,比如aaaacaaaac最优解为aRRcR(意会坑在哪里),踩了一次 #include ...

  5. Java编程基础-字符串

    在Java语言中,字符串数据实际上由String类所实现的.Java字符串类分为两类:一类是在程序中不会被改变长度的不变字符串:另一类是在程序中会被改变长度的可变字符串.Java环境为了存储和维护这两 ...

  6. chrome浏览器之网络面板

    这篇指导向你展示怎样检测网络张状况或者在chrome开发工具的网络面板中尽可能的优化网页. 排列的或受阻的请求 症状:同时发出六个请求.之后有一系列的请求排队或受阻.一旦最先的六个请求中有一个响应结束 ...

  7. 在页面实现qq跳转链接

    http://shang.qq.com/v3/widget/consult.html

  8. TFS数据库分离附加经验总结

    因TFS数据库已经100多G,所在的服务器D盘已没有空间满足tfs数据库的增长速度,故必须分离复制到其它盘.在分离过程中,先后分离了ReportServer.ReportServerTempDB.Tf ...

  9. SQL 时间日期函数

    1.获取当前日期GetDate getdate()函数以datetime数据类型的格式返回当前SQLServer服务器所在计算机的日期和时间.其语法格式为getdate().返回值舍入到最近的秒小数部 ...

  10. Linux OpenGL 实践篇-14-多实例渲染

    多实例渲染 OpenGL的多实例渲染是一种连续执行多条相同的渲染命令的方法,并且每条命令产生的结果都有轻微的差异,通常用于渲染大量的几何物体. 设想一个场景,比如太空,我们需要渲染数以万记的星球,如果 ...