题目描述

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

输入

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

输出

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

样例输入

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

样例输出

2


题解

树形dp

考虑如果给定根节点的话怎么做:

设 $f[i][j]$ 表示以 $i$ 为根的子树,$i$ 到根节点的简单路径上最后一个有色节点的颜色是 $j$ 的最小着色点数。

那么对于所有 $i$ 的儿子 $k$ ,有 $f[i][j]+=min(f[k][j],f[k][j\text{^}1])$ 。边界条件 $f[u][c[u]]=0,f[u][c[u]\text{^}1]=\infty$ ,其中 $u$ 是叶子节点。

那么 $min(f[root][0],f[root][1])+1$ 就是 $root$ 作为树根时的答案,其中 $+1$ 指的是根节点需要再着色一次。

一次dp的时间复杂度是 $O(n)$ ,我们可以枚举每个节点为根,复杂度为 $O(n^2)$ ,可过。

但是还有更优的做法:考虑根节点从 $x$ 变化到相邻的点 $y$ 的过程,那么 $x$ 为根时,$y$ 的着色只有两种情况:染了与 $x$ 不同的颜色、没有染色。

第一种情况显然换根后方案可以不变,第二种情况显然可以换根时把 $x$ 的着色该为染 $y$ ,答案不变。因此有 $ans_y\le ans_x$,同时从 $y$ 换到 $x$ 时有 $ans_x\le ans_y$ ,所以 $ans_x=ans_y$。

于是选择任意一个非叶节点作为根做一次dp即可,时间复杂度 $O(n)$

#include <cstdio>
#include <algorithm>
#define N 10010
using namespace std;
int head[N] , to[N << 1] , next[N << 1] , cnt , f[N][2];
inline void add(int x , int y)
{to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x , int fa)
{int i;for(i = head[x] ; i ; i = next[i])if(to[i] != fa)dfs(to[i] , x) , f[x][0] += min(f[to[i]][0] , f[to[i]][1] + 1) , f[x][1] += min(f[to[i]][1] , f[to[i]][0] + 1);
}
int main()
{int n , m , i , x , y;scanf("%d%d" , &m , &n);for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , f[i][x] = 0 , f[i][x ^ 1] = m;for(i = 1 ; i < m ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x);dfs(m , 0);printf("%d\n" , min(f[m][0] , f[m][1]) + 1);return 0;
}

转载于:https://www.cnblogs.com/GXZlegend/p/8059198.html

【bzoj1304】[CQOI2009]叶子的染色 树形dp相关推荐

  1. bzoj1304 [CQOI2009]叶子的染色 dfs+树形dp

    这个类型的题应该是做过很多次,但做起来还是比较慢 这个题常规方法是枚举根,但这样是n^2的,这样就考虑优化 可以作为根的点一定构成一棵树,所以每次找相邻的点一定可以考虑所有情况 然后就是如何用父节点的 ...

  2. 【树形dp】P3155 [CQOI2009]叶子的染色

    你的着色方案应该保证根结点到每个叶子的简单路径上都至少包含一个有色结点(哪怕是这个叶子本身). 由于题目的这一点要求,我们可以得出,叶子节点的着色方案只与其上方第一个有色节点有关,所以选择哪个节点做r ...

  3. [CQOI2009]叶子的染色

    传送门:https://www.luogu.org/problemnew/show/P3155 一道挺水的树形dp题,然后我因为一个挺智障的问题debug了一晚上-- 嗯--首先想,如果一个点的颜色和 ...

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

    链接:https://ac.nowcoder.com/acm/problem/19914 来源:牛客网 题目描述 给一棵m个结点的无根树,你可以选择一个度数大于1的结点作为根,然后给一些结点(根.内部 ...

  5. [BZOJ4033][HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 2437  Solved: 1034 [Submit][St ...

  6. bzoj4033: [HAOI2015]树上染色(树形dp)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MB Submit: 3269  Solved: 1413 [Submit][St ...

  7. 叶子的染色-基础树形dp

    题目描述 原题来自:CQOI 2009 给一棵有 m 个节点的无根树,你可以选择一个度数大于 11 的节点作为根,然后给一些节点(根.内部节点.叶子均可)着以黑色或白色.你的着色方案应保证根节点到各叶 ...

  8. #树形dp#jzoj 1010 洛谷 3155 叶子的颜色

    题目 对于每个叶结点u,定义c[u]为从u到根结点的简单路径上第一个有色结点的颜色.给出每个c[u]的值,设计着色方案,使得着色结点的个数尽量少. 分析 这道题可以用树形dp,f[x][0/1]f[x ...

  9. 0x54. 动态规划 - 树形DP(习题详解 × 12)

    目录 0x54.1 树形DP Problem A. 没有上司的舞会 Problem B. 战略游戏 0x54.2 树上背包 Problem A. 选课 Problem B.[数据加强版]选课(树上背包 ...

最新文章

  1. android应用课程设计报告,基于Android的多媒体播放器课程设计报告.doc
  2. javascript里的面向对象
  3. 2017c语言预测,2017计算机二级C语言上机最终预测题
  4. mysql多个on_在多个查询中插入多行的MySQL ON DUPLICATE KEY UPDATE
  5. Ubuntu安装中文语言包
  6. weka的java环境配置_windows下安装和配置Weka
  7. 为了杀蚊子,他用树莓派DIY了一把激光枪!
  8. Win11系统如何解除网络限制
  9. leetcode练习:292. Nim Game
  10. 【AD】AD20差分等长布线
  11. Photoshop 2021 for mac(PS2021直装版)中英双语版
  12. mongodb 的安装使用步骤
  13. 写代码有这16个好习惯,可以减少80%非业务的bug
  14. JAXWS CXF JAXB + MyEclipse + Maven Byron自學視頻04
  15. Go开发中配置一个Logger日志的功能实现(结合zap日志库)
  16. chrome浏览器 快捷键设置
  17. 微信小程序【生命周期】
  18. 币圈拉盘是什么意思?
  19. Jenkins 也宣布弃用 JDK 8,你还在用JDK8吗
  20. 用定时器T0查询方式P0口8位控制LED闪烁

热门文章

  1. 防火墙(16)——SNAT和DNAT,DNAT实践
  2. 合并两个有序数组—leetcode88
  3. lcx转发3389数据
  4. linux关于/etc/profile.d与/etc/profile的正确运用
  5. HDU Problem - 5101 Select(二分)
  6. sogou ubuntu安装(最后还是失败了,最近老失败,不知道为啥)
  7. c++ primer 5th,练习11.19,编写代码验证
  8. c++ 双端队列 deque 之 (头部、尾部)插入元素/删除元素/
  9. crontab定时任务运行
  10. 运筹学_单纯形表法_0(matlab实现)