【BZOJ1864】[Zjoi2006]三色二叉树 树形DP

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;
}
posted @ 2016-12-13 20:14  CQzhangyu  阅读(985)  评论(0编辑  收藏  举报