BZOJ1864 [ZJOI2006] 三色二叉树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1864
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
树DP
用f[x][0]表示编号为x的点不染成绿色,f[x][1]表示编号为x的点染成绿色
f[x][0] = max (或min) (f[l[x]][0] + f[r[x]][1], f[r[x]][0] + f[l[x]][1]);
f[x][1] = f[l[x]][0] + f[r[x]][0] + 1;
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define rep(i,l,r) for(int i=l; i<=r; i++) 5 #define clr(x,y) memset(x,y,sizeof(x)) 6 using namespace std; 7 const int INF = 0x3f3f3f3f; 8 const int maxn = 500010; 9 int tot=1,l[maxn],r[maxn],f[maxn][2]; 10 void dfs(int x){ 11 char ch = getchar(); 12 if (ch == '0') return; 13 tot++; l[x] = tot; dfs(tot); 14 if (ch == '2'){ 15 tot++; r[x] = tot; dfs(tot); 16 } 17 } 18 void dp1(int x){ 19 if (!x) return; 20 dp1(l[x]); dp1(r[x]); 21 f[x][0] = max(f[l[x]][0] + f[r[x]][1], f[r[x]][0] + f[l[x]][1]); 22 f[x][1] = f[l[x]][0] + f[r[x]][0] + 1; 23 } 24 void dp2(int x){ 25 if (!x) return; 26 dp2(l[x]); dp2(r[x]); 27 f[x][0] = min(f[l[x]][0] + f[r[x]][1], f[r[x]][0] + f[l[x]][1]); 28 f[x][1] = f[l[x]][0] + f[r[x]][0] + 1; 29 } 30 int main(){ 31 clr(l,0); clr(r,0); dfs(1); 32 clr(f,0); dp1(1); printf("%d ",max(f[1][0],f[1][1])); 33 clr(f,0); dp2(1); printf("%d\n",min(f[1][0],f[1][1])); 34 return 0; 35 }