[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 ...
随机推荐
- WinForm的TextBox限制只能输入数字并且屏蔽默认右键菜单
基于Window消息实现 class TextBoxExt:TextBox { private const int WM_RBUTTONDOWN = 0x0204; private const int ...
- 新版GRANAFA K8S插件 K8S NODE 图表不显示问题解决方法
原文:https://www.wchao.site/archives/granafa-k8s 其他参考:https://blog.csdn.net/bbwangj/article/details/82 ...
- CSS 多列布局
CSS3 新增多列布局适合排版很长的文字内容,让其多列显示. 一.多列布局 语法格式: columns:column-width | column-count; column-width:定义每列的宽 ...
- Spark高级函数应用【combineByKey、transform】
一.combineByKey算子简介 功能:实现分组自定义求和及计数. 特点:用于处理(key,value)类型的数据. 实现步骤: 1.对要处理的数据进行初始化,以及一些转化操作 2.检测key是否 ...
- Linux相关目录
Linux 启动流程 Linux--基本目录 Linux--selinux Linux--网卡配置 Linux--系统运行级别 Linux--重要文件
- Java变量常量声明和定义
一.常量和变量 1.常量变量定义 在程序中存在大量的数据来代表程序的状态,其中有些数据在程序的运行过程中值会发生改变,有些数据在程序运行过程中值不能发生改变,这些数据在程序中分别被叫做变量和常量. 2 ...
- 通过腾讯邮件服务器发送HTML邮件
邮件发送工具: private static String host = "smtp.exmail.qq.com";// 服务器地址 private static String p ...
- docker端口映射或启动容器时报错Error
现象: [root@localhost ~]# docker run -d -p 9000:80 centos:httpd /bin/sh -c /usr/local/bin/start.shd5b2 ...
- 大数据调度工具oozie详细介绍
背景 之前项目中的sqoop等离线数据迁移job都是利用shell脚本通过crontab进行定时执行,这样实现的话比较简单,但是随着多个job复杂度的提升,无论是协调工作还是任务监控都变得麻烦,我们选 ...
- Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested ...