【BZOJ-1864】三色二叉树 树形DP

1864: [Zjoi2006]三色二叉树

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 659  Solved: 469
[Submit][Status][Discuss]

Description

Input

仅有一行,不超过500000个字符,表示一个二叉树序列。

Output

输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。

Sample Input

1122002010

Sample Output

5 2

HINT

Source

Day1

Solution

傻逼题,树形DP

$f[x][0/1]$表示节点$x$是否绿色的最大值,$g[x][0/1]$表示最小值

$f[x][0]=f[son[x][0]][1]+f[son[x][1]][1]+1$

$f[x][1]=max(f[son[x][0]][0]+f[son[x][1]][1],f[son[x][0]][1]+f[son[x][1]][0])$

$g[x][0]=g[son[x][0]][1]+g[son[x][1]][1]+1$

$g[x][1]=min(g[son[x][0]][0]+g[son[x][1]][1],g[son[x][0]][1]+g[son[x][1]][0])$

一开始以为序列转树略麻烦于是手画两组,发现弱智转换....然后这题就是5min1A系列了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 500010
int son[maxn][2],sz=1,f[maxn][2],g[maxn][2];
void BuildTree(int x)
{
    int now=getchar();
    if (now>'9' || now<'0' || now==0) return;
    if (now=='1') son[x][0]=++sz,BuildTree(son[x][0]);
    if (now=='2')
        son[x][0]=++sz,BuildTree(son[x][0]),
        son[x][1]=++sz,BuildTree(son[x][1]);
}
void DPmax(int x)
{
    if (x==0) return;
    DPmax(son[x][0]),DPmax(son[x][1]);
    f[x][0]=f[son[x][0]][1]+f[son[x][1]][1]+1;
    f[x][1]=max(f[son[x][0]][0]+f[son[x][1]][1],f[son[x][0]][1]+f[son[x][1]][0]);
}
void DPmin(int x)
{
    if (x==0) return;
    DPmin(son[x][0]),DPmin(son[x][1]);
    g[x][0]=g[son[x][0]][1]+g[son[x][1]][1]+1;
    g[x][1]=min(g[son[x][0]][0]+g[son[x][1]][1],g[son[x][0]][1]+g[son[x][1]][0]);
}
int main()
{
    BuildTree(1);
    DPmax(1); DPmin(1);
    printf("%d %d
",max(f[1][1],f[1][0]),min(g[1][1],g[1][0]));
    return 0;
}
原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5482365.html