[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 ...
随机推荐
- 【数据库】Mysql配置参数
vim /ect/my.cnf 使用命令打开mysql的配置文件. 加入以下参数 [mysql] default-character-set=utf8 [mysqld] lower_case_tabl ...
- 树莓派安装window ioT
下载安装器 https://developer.microsoft.com/zh-cn/windows/iot/Downloads 操作设备
- C#中datatable操作
//1.新建datatable,为其添加自定义列DataTable dt = new DataTable();dt.Columns.AddRange(new DataColumn[] { new Da ...
- Mybatis映射器接口代理对象的方式 运行过程
查询一张表的所有数据. 环境: 使用工具IntelliJ IDEA 2018.2版本. 创建Maven工程不用骨架 1.pom.xml <?xml version="1.0" ...
- 31、splice()用法
改变数组,向数组中添加/删除元素: eg: 1.删除元素: let arr=['bob','lily','bike','sam']; arr.splice(2,1) console.log(arr) ...
- Qt使用QPainter绘制矢量图并保存为svg文件
位图和矢量图: Bitmap: Usually a larger file size Cannot be enlarged into a higher resolution as the image ...
- win10系统下安装Ubuntu18.04双系统
1.http://releases.ubuntu.com/18.04/ubuntu-18.04.2-desktop-amd64.iso下载Ubuntu 18.04镜像,准备好一个空的U盘 2.下载ru ...
- linux 账户控制
用户 用户是能够获取系统资源的权限的集合. linux用户组的分类: 管理员 root :具有使用系统所有权限的用户,其UID 为0. 普通用户 : 即一般用户,其使用系统的权限受限,其UID为500 ...
- find 和grep的区别
find(以文件属性为查找条件) grep(以文件内容为查找条件) grep works /usr/local/apache/htdocs/index.html 1.将/etc/passwd,有出现 ...
- Unexpected EOF in archive 或者 rmtlseek not stopped at a record boundary
多半都是文件在传输.复制的时候,发生了损坏: 尽量cp不要用mv 其次,注意文件的大小: