BZOJ-1864-[Zjoi2006]三色二叉树(树形dp)

Description

Input

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

Output

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

Sample Input

1122002010

Sample Output

5 2

HINT

 

Source

 

题解

这道题我们考虑dp

我们先把树给构造出来(可以用栈,也可以用dfs)

建完树后,我们用f[i][0/1/2][0]表示i节点填绿/蓝/红色的最小答案,f[i][0/1/2][1]表示i节点填绿/蓝/红色的最大答案

我们考虑i节点从两个儿子转移

f[i][0][0]=min(f[s1][1][0]+f[s2][2][0],f[s1][2][0]+f[s2][1][0])

f[i][1][0]=min(f[s1][0][0]+f[s2][2][0],f[s1][2][0]+f[s2][0][0])

f[i][2][0]=min(f[s1][0][0]+f[s2][1][0],f[s1][1][0]+f[s2][0][0])

f[i][0/1/2][1]转移同理

 1 #include<bits/stdc++.h>
 2 #define N 500005
 3 using namespace std;
 4 int tot,top;
 5 int Stack[N];
 6 int f[N][3][2];
 7 char s[N];
 8 int main(){
 9     scanf("%s",s+1);
10     int len=strlen(s+1);
11     for (int i=len;i>=1;i--)
12         if (s[i]=='2'){
13             int x=Stack[top],y=Stack[--top];
14             tot++;
15             f[tot][0][0]=min(f[x][1][0]+f[y][2][0],f[x][2][0]+f[y][1][0])+1;
16             f[tot][1][0]=min(f[x][2][0]+f[y][0][0],f[x][0][0]+f[y][2][0]);
17             f[tot][2][0]=min(f[x][1][0]+f[y][0][0],f[x][0][0]+f[y][1][0]);
18             f[tot][0][1]=max(f[x][1][1]+f[y][2][1],f[x][2][1]+f[y][1][1])+1;
19             f[tot][1][1]=max(f[x][2][1]+f[y][0][1],f[x][0][1]+f[y][2][1]);
20             f[tot][2][1]=max(f[x][1][1]+f[y][0][1],f[x][0][1]+f[y][1][1]);
21             Stack[top]=tot;
22         } else
23         if (s[i]=='1'){
24             int x=Stack[top];
25             tot++;
26             f[tot][0][0]=min(f[x][1][0],f[x][2][0])+1;
27             f[tot][1][0]=min(f[x][0][0],f[x][2][0]);
28             f[tot][2][0]=min(f[x][0][0],f[x][1][0]);
29             f[tot][0][1]=max(f[x][1][1],f[x][2][1])+1;
30             f[tot][1][1]=max(f[x][0][1],f[x][2][1]);
31             f[tot][2][1]=max(f[x][0][1],f[x][1][1]);
32             Stack[top]=tot;
33         } else{
34             tot++;
35             f[tot][0][0]=f[tot][0][1]=1;
36             Stack[++top]=tot;
37         }
38     int Max=max(f[tot][0][1],max(f[tot][1][1],f[tot][2][1]));
39     int Min=min(f[tot][0][0],min(f[tot][1][0],f[tot][2][0]));
40     printf("%d %d",Max,Min);
41     return 0;
42 } 
View Code

 

posted @ 2017-11-06 19:50  I__am  阅读(144)  评论(0编辑  收藏  举报