题目描述
输入输出格式
输入格式:输入文件名:TRO.IN
输入文件仅有一行,不超过500000个字符,表示一个二叉树序列。
输出格式:输出文件名:TRO.OUT
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
输入输出样例
输入样例#1:
1122002010
输出样例#1:
5 2
树形dp
可以发现,只要不是绿色,红色或蓝色对于答案是没有影响的。
所以题目变成:在一棵二叉树上,每个有两个儿子的节点和他的2个儿子中一定要有一个绿色节点切相邻的两个节点不能同时是绿色时求绿色节点数量的最大值和最小值。
然后就是基础的树形dp啦!要注意的是这道题的建图需要一定的技巧。
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; int i,m,n,j,k,a[500005][4],f[500005],son[500005][2],d[500005]; int dfs(int x,int fa) { scanf("%1ld",&d[x]); f[x]=fa; if(fa) { if(son[fa][0]) son[fa][1]=x; else son[fa][0]=x; } if(d[x]==0) return x; if(d[x]==2) return dfs(dfs(x+1,x)+1,x); return dfs(x+1,x); } void ddfs(int x) { if(!x) return; if(!d[x]) { a[x][1]=a[x][3]=1; return; } ddfs(son[x][0]); ddfs(son[x][1]); a[x][0]=max(a[son[x][0]][1]+a[son[x][1]][0],a[son[x][0]][0]+a[son[x][1]][1]); a[x][1]=1+a[son[x][0]][0]+a[son[x][1]][0]; a[x][2]=min(a[son[x][0]][3]+a[son[x][1]][2],a[son[x][0]][2]+a[son[x][1]][3]); a[x][3]=1+a[son[x][0]][2]+a[son[x][1]][2]; } int main() { dfs(1,0); ddfs(1); printf("%d %d",max(a[1][0],a[1][1]),min(a[1][2],a[1][3])); }