首页 > 其他分享 >叶子的颜色

叶子的颜色

时间:2023-08-19 11:45:52浏览次数:31  
标签:颜色 idx int 染成 叶子 节点

叶子的颜色

给一棵有 $m$ 个节点的无根树,你可以选择一个度数大于 $1$ 的节点作为根,然后给一些节点(根、内部节点、叶子均可)着以黑色或白色。

你的着色方案应保证根节点到各叶子节点的简单路径上都至少包含一个有色节点,哪怕是这个叶子本身。

对于每个叶子节点 $u$,定义 $c_u$ 为从根节点到 $u$ 的简单路径上最后一个有色节点的颜色。

给出每个 $c_u$ 的值,设计着色方案使得着色节点的个数尽量少。

输入格式

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

接下来 $n$ 行每行一个 $0$ 或 $1$ 的数,其中 $0$ 表示黑色,$1$ 表示白色,依次为 $c_1,c_2, \ldots, c_n$ 的值。

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

输出格式

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

数据范围

数据 $1$ $2$ $3$ $4$ $5$ $6$ $7$ $8$ $9$ $10$
$M$ $10$ $50$ $100$ $200$ $400$ $1000$ $4000$ $8000$ $10000$ $10000$
$N$ $5$ $23$ $50$ $98$ $197$ $498$ $2044$ $4044$ $5021$ $4996$

输入样例:

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

输出样例:

2

 

解题思路

  首先一定是有解的,先随便选择一个度数大于$1$的节点作为整棵树的根节点,然后直接对每个叶子节点$u$涂上对应的颜色$c_u$即可。不过可以发现这肯定不是最优的解法,假如有$k$个叶子的父节点相同,并且这$k$个叶子节点中有$x$个被染成白色,$y$个染成黑色(满足$x+y=k$),那么我们可以把这个父节点染成$x$和$y$中最大的那个所对应的颜色,然后再将这个颜色的叶子改成透明,这样染色的节点数目就变成了$k-\max\{x,y\}+1$,比原来的$k$要小。以此类推,从叶子不断往上重复这个步骤,直到根节点。

  以样例为例,选取$5$号点作为根节点,如下图:

  很明显当儿子染成白色和黑色的数目不相同时,父亲应该染成颜色最多的那个更优。而如果儿子染成黑白的数目相同时,父亲染成这两种颜色都是最优解,这时情况就不唯一了,最终父亲要染成什么颜色还要取决于与它同层的兄弟节点染成什么颜色最优。这当然可以通过枚举所有的情况然后取最优解,但我们可以用dp来避免重复枚举。

  可以发现当我们往上刚走到父节点时,此时所有的儿子都是染了色的,经过操作后父节点也必然会染色(相应的儿子改为透明)。因此定义状态$f(u,j)$表示考虑以$u$为根的子树,且$u$被染成颜色$j$时的所有合法方案的染色最小数目。由于$u$的每棵子树是相互独立的,且儿子$v_i$也必然染了颜色,因此状态转移方程就是$$f(u,j) = 1 + \sum\limits_{i=1}^{k}{\min\left\{f(v_i,j)-1, f(v_i,\bar{j})\right\}}$$

  其中加$1$是因为$u$要染色,$f(v_i,j)-1$表示儿子与父亲染成一样的颜色,因此儿子改成透明,$f(v_i,\bar{j})$表示儿子与父亲染的颜色不同。

  最后我们只需任选一个度数大于$1$的节点作为根节点跑一遍dfs即可,因为对于任意一个根节点分析的方法是一样的,得到的最优解也是一样的。

  AC代码如下,时间复杂度为$O(n+m)$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 1e4 + 10, M = N * 2;
 5 
 6 int n, m;
 7 int c[N];
 8 int head[N], e[M], ne[M], idx;
 9 int f[N][2];
10 
11 void add(int v, int w) {
12     e[idx] = w, ne[idx] = head[v], head[v] = idx++;
13 }
14 
15 void dfs(int u, int pre) {
16     if (u <= m) {
17         f[u][c[u]] = 1;
18         return;
19     }
20     f[u][0] = f[u][1] = 1;
21     for (int i = head[u]; i != -1; i = ne[i]) {
22         if (e[i] != pre) {
23             dfs(e[i], u);
24             f[u][0] += min(f[e[i]][0] - 1, f[e[i]][1]);
25             f[u][1] += min(f[e[i]][1] - 1, f[e[i]][0]);
26         }
27     }
28 }
29 
30 int main() {
31     scanf("%d %d", &n, &m);
32     for (int i = 1; i <= m; i++) {
33         scanf("%d", c + i);
34     }
35     memset(head, -1, sizeof(head));
36     for (int i = 0; i < n - 1; i++) {
37         int v, w;
38         scanf("%d %d", &v, &w);
39         add(v, w), add(w, v);
40     }
41     memset(f, 0x3f, sizeof(f));
42     dfs(n, -1);
43     printf("%d", min(f[n][0], f[n][1]));
44     
45     return 0;
46 }

 

参考资料

  [CQOI2009] 叶子的颜色 解题报告(树形DP) :https://www.cnblogs.com/xxzh/p/9278487.html

  AcWing 1079. 叶子的颜色(蓝桥杯集训·每日一题):https://www.acwing.com/video/4671/

标签:颜色,idx,int,染成,叶子,节点
From: https://www.cnblogs.com/onlyblues/p/17642238.html

相关文章

  • 给定n个多种颜色的球,如何将球分组,保证每组内球颜色不能相同,且分组的数量要最小。
    usingSystem;usingSystem.Collections.Generic;publicclassBallColorGroup{publicintColor{get;set;}publicintCount{get;set;}}publicclassBallColorGrouping{publicstaticList<List<int>>GroupBalls(List<int&g......
  • echarts 背景颜色透明和提示框背景颜色与透明度
    echarts背景颜色透明描述:使用'dark'系列主题初始化控件,控件会自带黑色背景色,与页面整体风格不符合,所以需要将其背景颜色设置为透明.官网文档:http://echarts.baidu.com/option.html#backgroundColor方法一:varoption={backgroundColor:'rgba(128,128,128,0.1)'//r......
  • 代码随想录算法训练营第十七天| 110.平衡二叉树 257. 二叉树的所有路径 404.左叶子
     卡哥建议:迭代法,大家可以直接过,二刷有精力的时候 再去掌握迭代法。  110.平衡二叉树 (优先掌握递归)   卡哥建议:再一次涉及到,什么是高度,什么是深度,可以巩固一下。   题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.%E5%B9%B3%E8%A1%A1%E4%BA%8C%......
  • 在Typora中使用AutoHotkey 2.0实现使用快捷键设置文本颜色
    使用Typora时不能设置文本颜色,总是觉得不方便,于是在网上搜索,发现有个小工具:AutoHotkey,编写脚本后,通过快捷键的方式可以设置Typora的文本颜色。下载软件到https://www.autohotkey.com/这个网址下载AutoHotkey并安装脚本实现网上很多实现方式都是基于AutoHotkeyv1.0、v1.1的,Au......
  • v-charts 自定义堆叠面积图背景颜色
    下载npmiv-charts-Smain.js引入importVeLinefrom'v-charts/lib/line.common'Vue.component(VeLine.name,VeLine)使用<ve-line:data="chartData":settings="chartSettings"></ve-line>exportdefault{data(){......
  • teamcenter awc 开发-柱状图、饼状图修改颜色
    1、在对应的chartProviders下面添加"chartColorOverrideClass":"hf_aw-charts-chartColor"2、在src下创建一个scss文件@import'mixins/mixins';.hf_aw-charts-chartColor1{   background-color:#426ab3;}.hf_aw-charts-chartColor2{   backgroun......
  • 【leetcode】404 左叶子之和
    https://leetcode.cn/problems/sum-of-left-leaves/description/【分析】该题要求左叶子之和。如果我们对当前节点进行叶子节点的判断,那么我们是不知道当前节点是左叶子还是右叶子的。所以我们应该在叶子结点的上层(父节点)进行判断。【代码】classSolution:defsumOfL......
  • VTK 实例5:设置椎体颜色属性
    1#include"vtkAutoInit.h"2VTK_MODULE_INIT(vtkRenderingOpenGL2);3VTK_MODULE_INIT(vtkInteractionStyle);45#include<vtkConeSource.h>//源数据6#include<vtkPolyDataMapper.h>//数据映射7#include<vtkRenderer.h>//绘制器8#......
  • 13.1.1 翻转裁减,改变颜色,结合多种图像增广方法进行图像增广
    一.图像增广的好处随机改变训练样本可以减少模型对某些属性的依赖,从而提高模型的泛化能力。裁剪图像可以减少模型对于对象出现位置的依赖以不同的方式裁剪图像,使感兴趣的对象出现在不同的位置,减少模型对于对象出现位置的依赖调整亮度、颜色等因素可以降低模型对颜色的敏感度。二......
  • 左叶子节点之和
    首先将非终止条件,非递归函数部分叫做单层递归。思考过程如下:想解题思路:一个节点的左节点的左节点为空,左节点的右节点为空,那么这个结点就是左叶子结点,那么我们就要给它的数值加到sum上去解题思路即为单层递归,那么将单层递归写成程序为:1if((node->left->left==nullpt......