1864: [Zjoi2006]三色二叉树
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5
2
题解:经典的树形DP题。用f[i]表示点i是绿色时最多有多少个点能被染成绿色,g[i]表示i不是绿色时最多有多少个点被染成绿色,容易推出状态转移方程:
f[i]=g[ch[i][0]]+g[ch[i][1]]+1;
g[i]=max(f[ch[i][0]]+g[ch[i][1]],f[ch[i][1]]+g[ch[i][0]]);
最小值把max换成min即可。
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; const int maxn=500010; char str[maxn]; int sta[maxn],top; int f[maxn],g[maxn],ch[maxn][2]; int n; int main() { scanf("%s",str); n=strlen(str); int i,j; for(i=1;i<=n;i++) { if(ch[sta[top]][0]) ch[sta[top]][1]=i; else ch[sta[top]][0]=i; top--; for(j=1;j<=str[i-1]-'0';j++) sta[++top]=i; } for(i=n;i>=1;i--) { f[i]=g[ch[i][0]]+g[ch[i][1]]+1; g[i]=max(f[ch[i][0]]+g[ch[i][1]],f[ch[i][1]]+g[ch[i][0]]); } printf("%d ",max(f[1],g[1])); for(i=n;i>=1;i--) { f[i]=g[ch[i][0]]+g[ch[i][1]]+1; g[i]=min(f[ch[i][0]]+g[ch[i][1]],f[ch[i][1]]+g[ch[i][0]]); } printf("%d",min(f[1],g[1])); return 0; }