[Zjoi2006]三色二叉树(bzoj1864)(洛谷2585)题解
原题地址: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)题解的更多相关文章
- BZOJ1864[ZJOI2006]三色二叉树[树形DP]
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 773 Solved: 548[Submit][Status] ...
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...
- bzoj千题计划212:bzoj1864: [Zjoi2006]三色二叉树
http://www.lydsy.com/JudgeOnline/problem.php?id=1864 #include<cstdio> #include<cstring> ...
- 嘴巴题5 「BZOJ1864」[ZJOI2006] 三色二叉树
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1195 Solved: 882 [Submit][Status ...
- BZOJ 1864: [Zjoi2006]三色二叉树( 树形dp )
难得的ZJOI水题...DFS一遍就行了... ----------------------------------------------------------------------- #inc ...
- BZOJ_1864_[Zjoi2006]三色二叉树_树形DP
BZOJ_1864_[Zjoi2006]三色二叉树_树形DP 题意: 分析:递归建树,然后DP,从子节点转移. 注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的.这样的话我们只需要知道当 ...
- 【BZOJ】1864: [Zjoi2006]三色二叉树
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1295 Solved: 961[Submit][Status ...
- 1864: [Zjoi2006]三色二叉树
1864: [Zjoi2006]三色二叉树 链接 分析: 做得最智障的一题了... 首先中间输出两个数之间没空格(换行居然也过了...), 写了dp[i][0/1/2],后来知道其实dp[i][0/1 ...
- [ZJOI2006]三色二叉树
[ZJOI2006]三色二叉树 BZOJ luogu 分3种颜色讨论转移一下 #include<bits/stdc++.h> using namespace std; const int ...
- luogu P2585 [ZJOI2006]三色二叉树
P2585 [ZJOI2006]三色二叉树 题目描述 输入输出格式 输入格式: 输入文件名:TRO.IN 输入文件仅有一行,不超过10000个字符,表示一个二叉树序列. 输出格式: 输出文件名:TRO ...
随机推荐
- 如何判断两个IP地址是不是处于同一网段?
个人理解,欢迎指正. 一.要判断两个IP地址是不是在同一个网段,就将它们的IP地址分别与子网掩码做与运算,得到的结果-->网络号,如果网络号相同, 就在同一子网,否则,不在同一子网. 例:假定选 ...
- javascript 对象之hasOwnProperty()方法
hasOwnProperty()方法是判断某一个对象是否有你给出的属性名称,需要注意的是该方法无法检测该对象原型连中是否具有该属性 具体格式下: var person = {"name&qu ...
- (原创)C#监控软件通信模型
直接操作现场的设备是PLC,不是服务器和客户端.所以,以PLC为核心分析设备故障以及在PC端的C#程序中加入故障处理代码. PC端读和写PLC哪个重要?写重要.因为写会影响PLC的寄存器值,进而影响工 ...
- person类与其子类在使用中的内存情况(含java的改写和c#的屏蔽)
JAVA 普通person类及调用代码: public class Person { public String xm; public int nl; public void setme(String ...
- 关于springMVC中的路径问题
相对路径中,我们最后想要的到的是绝对路径,而绝对路径=参照路径+相对路径: 相对路径往往都知道,只需要区分参照路径即可:对于前台和后台,参照路径不太相同: 什么是前台,后台路径: 前台路径: 出现在 ...
- CSS中:和::
一个冒号是伪类,两个冒号是伪元素 伪类可以独立于文档的元素来分配样式,且可以分配给任何元素,逻辑上和功能上类类似,但是其是预定义的.不存在于文档树中且表达方式也不同,所以叫伪类.伪元素所控制的内容和一 ...
- 14、vue-cli脚手架搭建项目
1:全局安装vue-cli:npm install --global vue-cli2:进入你的项目目录:cd myProject3:初始化创建项目:vue init webpack vue-demo ...
- java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libjni_i
出错log:java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libskytvjni.so" ...
- Linux基础:sort命令总结
本文只总结一些常用的用法,更详细的说明见man sort和sort --help. sort命令 sort命令用于串联排序指定文件并将结果写到标准输出. sort可以指定按照何种排序规则进行排序,如按 ...
- PHP实现Redis单据锁,防止并发重复写入
一.写在前面 在整个供应链系统中,会有很多种单据(采购单.入库单.到货单.运单等等),在涉及写单据数据的接口时(增删改操作),即使前端做了相关限制,还是有可能因为网络或异常操作产生并发重复调用的情况, ...