1864: [Zjoi2006]三色二叉树
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 659 Solved: 469
[Submit][Status][Discuss]
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
HINT
Source
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; }