标签:请求 root content printf dfs NPU 颜色不同 技术 左右
一棵二叉树可以按照如下规则表示成一个由 \(0、1、2\) 组成的字符序列,我们称之为 “二叉树序列 \(S\)”:
\(S= \begin{cases} 0 \ \ \ \ \ \ \ \ \ \ 表示该树没有子节点 \newline 1S_1 \ \ \ \ \ \ 表示该树有一个子节点,S_1 为其子树的二叉树序列 \newline 2S_1S_2 \ \ 表示该树有两个子节点,S_1 和 S_2 分别表示其两个子树的二叉树序列 \end{cases}\)
例如,下图所表示的二叉树可以用二叉树序列 \(S=21200110\) 来表示。
你的任务是要对一棵二叉树的节点进行染色。
每个节点可以被染成红色、绿色或蓝色。
并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。
给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。
仅有一行,表示一个二叉树序列。
只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
输入序列长度不超过 \(5 \times 10^5\)。
1122002010
5 2
每一个节点可以染三种颜色,红黄绿三种,要求父子节点颜色不同,而且左右儿子之间的颜色也要不同,问有多少个节点可以染色为绿色
这是一棵树。
这棵树父子节点之前存在一定的限制关系。
题目要求最值计数
根据上面的这些分析,我们不难得出本题需要用树形DP
既然本题要用动态规划,那么我们得严格按照,以下顺序求解本题。
首先,我们来设计状态。
状态的属性必然是,可以染绿色的节点最多是多少。
接着,根据树形DP最常见的状态设计为:
一个节点,及其子树再满足条件的情况下,答案是多少?
所以我们不难设计出:
这是初级的状态设计,我们还需要通过在分析状态转移的过程中,明确如何完善状态的设计。
接下来,设计状态转移。
分析题目的限制条件,来约束状态转移,使其满足不重复不遗漏。
接下来罗列一下约束条件:
那么此时我们发现,如果还是初级的状态设计,是没有办法转移的。
因为我们并不知道每个节点的染色情况,那么也无法转移了。
所以我们需要优化状态设计
这样,我们就彻底完成了状态设计,那么接下来开始状态转移。
如果说:
那么显然
f[x][i]=max(f[son_a][a]+f[son_b][b],f[son_a][b]+f[son_b][a]);
g[x][i]=min(g[son_a][a]+g[son_b][b],g[son_a][b]+g[son_b][a]);
//f[son_a][a]为左儿子选择颜色a,f[son_b][b]为右儿子选择颜色b
//f[son_a][b]为左儿子选择颜色b,f[son_b][a]为右儿子选择颜色a
//在这里a,b的定义不同于上面,指的是两种颜色,而且满足a,b不是当前节点的颜色
//f[x][i]为当前节点x选择颜色为i的绿色节点最大值,g[x][i]为最小值
如果说只有一个儿子节点,状态转移方程有所不同,但是和上面思路一样,具体可以直接看代码。
//My English is poor.The Code maybe have some grammer problems.
//To have a better Font display in Acwing.com,I must choose English.
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+20;
char s[N];
int tot,tree[N][3],f[N][3],g[N][3],Size[N];
void dfs(int root)//Build the Tree
{
Size[root]=s[root]-‘0‘;//count the number of sons
if (s[root]>=‘1‘)//left son
{
tree[root][0]=++tot;
dfs(tot);
}
if (s[root]==‘2‘)//right son
{
tree[root][1]=++tot;
dfs(tot);
}
}
void tree_DP(int x)
{
if (Size[x]==0)//The node is a leaf node
{
f[x][2]=g[x][2]=1;
return ;
}
for(int i=0; i<Size[x]; i++)//son
tree_DP(tree[x][i]);
for(int i=0; i<=2; i++)//color
{
int a=(i+1)%3,b=(i+2)%3;//other colors
int son_a=tree[x][0],son_b=tree[x][1];//other sons
if (Size[x]==1)//only a son
{
f[x][i]=max(f[son_a][a],f[son_a][b]);
g[x][i]=min(g[son_a][a],g[son_a][b]);
}
if (Size[x]==2)//two sons
{
f[x][i]=max(f[son_a][a]+f[son_b][b],f[son_a][b]+f[son_b][a]);
g[x][i]=min(g[son_a][a]+g[son_b][b],g[son_a][b]+g[son_b][a]);
}
if (i==2)//the now node chooses the green color
f[x][i]++,g[x][i]++;
// printf("%d %d %d\n",x,f[x][i],g[x][i]);
}
}
inline void out()//Output
{
int ans_Min=1e9,ans_Max=0;
for(int i=0; i<=2; i++)
{
ans_Min=min(ans_Min,g[1][i]);
ans_Max=max(ans_Max,f[1][i]);
}
printf("%d %d\n",ans_Max,ans_Min);
}
inline void init()//Input
{
scanf("%s",s+1);
tot=1;
dfs(1);
}
signed main()
{
init();
tree_DP(1);
out();
return 0;
}
标签:请求 root content printf dfs NPU 颜色不同 技术 左右
原文地址:https://www.cnblogs.com/gzh-red/p/14207484.html