原题地址:https://www.luogu.org/problemnew/show/P2585

题目大意:可以把一个节点染成三种颜色,父节点和两个子节点(可以有一个)颜色不能相同。求最多(少)能有多少个点能被染成绿色


由于是一棵树,多决策的问题,很明显的树形DP。

关于树形DP详见https://www.cnblogs.com/lizitong/p/10020914.html

二维状态,dp[i][j] j取0,1,2表示三种颜色。表示以这个编号为父节点取这个颜色时候有dp[i][j]个点能被染成绿色。

DFS搜到最底,然后给叶节点附上初值。

然后回溯更新。

以最小值为例。

dpmi[x][1] = min(dpmi[x][1],min(dpmi[l[x]][2]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][2])+1);
dpmi[x][2] = min(dpmi[x][2],min(dpmi[l[x]][1]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][1]));
dpmi[x][3] = min(dpmi[x][3],min(dpmi[l[x]][1]+dpmi[r[x]][2],dpmi[l[x]][2]+dpmi[r[x]][1]));

如果这个点是绿色,就比较子节点分别为其他两种颜色的大小,然后+1

如果这个点是其他颜色,就比较这两个点子节点分别是另外两种颜色和的大小。

最后输出父节点的最大(小)状态。

分别用l和r数组存左右儿子。

细节较多,上代码。

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#define N 500005
using namespace std;
char c[N];
struct edge
{
int to;
int nxt;
int from;
}eg[N];
int head[N];
int cnt = ;
int ct = ;
int dpma[N][];
int dpmi[N][];
int l[N];
int r[N];
void add(int x,int y)
{
eg[cnt].to = y;
eg[cnt].nxt = head[x];
eg[cnt].from = x;
head[x] = cnt++;
}
void buildtree(int x)
{
if(c[x]=='')
{
add(x,++ct);
l[x] = ct;
buildtree(ct);
add(x,++ct);
r[x] = ct;
buildtree(ct);
}else if(c[x]=='')
{
add(x,++ct);
l[x] = ct;
buildtree(ct);
}else
{
return ;
}
}
void dfsma(int x)
{
if(l[x]==&&r[x]==)
{
dpma[x][] = ;
return ;
}else
{
if(l[x])
{
dfsma(l[x]);
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][])+);
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][]));
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][]));
}
if(r[x])
{
dfsma(r[x]);
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][])+);
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][]));
dpma[x][] = max(dpma[x][],max(dpma[l[x]][]+dpma[r[x]][],dpma[l[x]][]+dpma[r[x]][]));
}
}
}
void dfsmi(int x)
{
if(l[x]==&&r[x]==)
{
dpmi[x][] = ;
dpmi[x][] = ;
dpmi[x][] = ;
return ;
}else
{
if(l[x])
{
dfsmi(l[x]);
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][])+);
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][]));
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][]));
}
if(r[x])
{
dfsmi(r[x]);
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][])+);
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][]));
dpmi[x][] = min(dpmi[x][],min(dpmi[l[x]][]+dpmi[r[x]][],dpmi[l[x]][]+dpmi[r[x]][]));
}
}
}
int main()
{
scanf("%s",c+);
buildtree();
memset(dpmi,0x3f,sizeof(dpmi));
dpmi[][] = ;
dpmi[][] = ;
dpmi[][] = ;
dfsma();
dfsmi();
printf("%d ",max(max(dpma[][],dpma[][]),dpma[][]));
printf("%d",min(min(dpmi[][],dpmi[][]),dpmi[][]));
}

[Zjoi2006]三色二叉树(bzoj1864)(洛谷2585)题解的更多相关文章

  1. BZOJ1864[ZJOI2006]三色二叉树[树形DP]

    1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 773  Solved: 548[Submit][Status] ...

  2. 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP

    1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...

  3. bzoj千题计划212:bzoj1864: [Zjoi2006]三色二叉树

    http://www.lydsy.com/JudgeOnline/problem.php?id=1864 #include<cstdio> #include<cstring> ...

  4. 嘴巴题5 「BZOJ1864」[ZJOI2006] 三色二叉树

    1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1195 Solved: 882 [Submit][Status ...

  5. BZOJ 1864: [Zjoi2006]三色二叉树( 树形dp )

    难得的ZJOI水题...DFS一遍就行了... ----------------------------------------------------------------------- #inc ...

  6. BZOJ_1864_[Zjoi2006]三色二叉树_树形DP

    BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...

  7. 【BZOJ】1864: [Zjoi2006]三色二叉树

    1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 1295  Solved: 961[Submit][Status ...

  8. 1864: [Zjoi2006]三色二叉树

    1864: [Zjoi2006]三色二叉树 链接 分析: 做得最智障的一题了... 首先中间输出两个数之间没空格(换行居然也过了...), 写了dp[i][0/1/2],后来知道其实dp[i][0/1 ...

  9. [ZJOI2006]三色二叉树

    [ZJOI2006]三色二叉树 BZOJ luogu 分3种颜色讨论转移一下 #include<bits/stdc++.h> using namespace std; const int ...

  10. luogu P2585 [ZJOI2006]三色二叉树

    P2585 [ZJOI2006]三色二叉树 题目描述 输入输出格式 输入格式: 输入文件名:TRO.IN 输入文件仅有一行,不超过10000个字符,表示一个二叉树序列. 输出格式: 输出文件名:TRO ...

随机推荐

  1. MySQL“慢SQL”定位

    MySQL"慢SQL"定位 数据库调优我个人觉得必须要明白两件事 1.定位问题(你得知道问题出在哪里,要不然从哪里调优呢) 2.解决问题(这个没有基本的方法来处理,因为不同的问题处 ...

  2. 如何判断两个IP地址是不是处于同一网段?

    个人理解,欢迎指正. 一.要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果-->网络号,如果网络号相同, 就在同一子网,否则,不在同一子网. 例:假定选 ...

  3. php 逻辑题

    越长大约发现,高中学的数学,都还给了数学老师,一点都没有留住. 最近遇到了一个 逻辑题,然后想了半天,后来做出来了,我就发现了,我可能是一个假的理科生.很简单的样子. 废话不说,看看这道题吧. /** ...

  4. C#条码生成及打印实例代码

    ";//条码 ; ; //打印按钮 private void button1_Click(object sender, EventArgs e) { //实例化打印对象 PrintDocum ...

  5. Entity Framework Core今日所得:避免 IEnumerable 以及 IQueryable 陷阱

    避免 IEnumerable 以及 IQueryable 陷阱: IEnumerable示用Linq会先去数据库查询所有记录,然后再条件查询. IQueryable接口派生自IEnumerable,但 ...

  6. java jsp文件报错解决方法

    初次使用java开发 下载好代码之后,用maven编译都是ok的,第二天,打开项目一看,好的web项目的jsp文件提示错误,后面,查了下问题,是tomcat没有配置路径导致的问题,现在大致记录一下解决 ...

  7. 虚拟化x86的三种途径

    虚拟化x86的三种途径 作者:缪天翔链接:https://www.zhihu.com/question/20145026/answer/34527331 x86上的全系统虚拟化有三种主要的途径: 二进 ...

  8. 1.ZooKeeper ACL权限控制

    参考:https://blog.csdn.net/liuxiao723846/article/details/79391650 ZK 类似文件系统,Client 可以在上面创建节点.更新节点.删除节点 ...

  9. 一篇文章搞定redis

    Redis 简介 Redis 是完全开源免费的,遵守 BSD 协议,是一个高性能的 key - value 数据库 Redis 与 其他 key - value 缓存产品有以下三个特点: Redis ...

  10. mybatis关联映射一对一

    在项目开发中,会存在一对一的关系,比如一个人只有一个身份证,一个身份证只能给一个人使用,这就是一对一关系.一对一关系使用主外键关联. table.sql,在数据库中创建如下两个表并插入数据 CREAT ...