您的位置:首页 > 其它

BZOJ 1864 三色二叉树(树DP)

2015-07-13 21:06 435 查看

Description



Input

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

Output

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

Sample Input

1122002010

Sample Output

5 2

树DP问题:经典的去最大和最小=-=没啥说的,递归建树。

dp[i][0]: i节点不为绿色获得的最大收益
dp[i][1]:i节点为绿色获得的最大收益
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
const int INF=0x3f3f3f3f;
typedef long long LL;
const int maxn=1e5+100;
int l[maxn],r[maxn],sz;
LL dp[maxn][2];//三种颜色的最多的那个1:NOT 绿 2:绿
char str[maxn];
void dfs(int x)
{
    if(str[x-1]=='0')
        return ;
    sz++;l[x]=sz;
    dfs(sz);
    if(str[x-1]=='2')
    {
        sz++;
        r[x]=sz;
        dfs(sz);
    }
}
void hehe1(int u)
{
    if(!u)
        return ;
    dp[u][1]=1;
    dp[u][0]=0;
    hehe1(l[u]);
    hehe1(r[u]);
    dp[u][1]+=dp[l[u]][0]+dp[r[u]][0];
    dp[u][0]+=max(dp[l[u]][0]+dp[r[u]][1],dp[l[u]][1]+dp[r[u]][0]);//选其他颜色
}
void hehe2(int u)
{
    if(!u)
        return ;
    dp[u][1]=1;
    dp[u][0]=0;
    hehe2(l[u]);
    hehe2(r[u]);
    dp[u][1]+=dp[l[u]][0]+dp[r[u]][0];
    dp[u][0]+=min(dp[l[u]][0]+dp[r[u]][1],dp[l[u]][1]+dp[r[u]][0]);//选其他颜色
}
int main()
{
    int mi,mx;
    while(~scanf("%s",str))
    {
        CLEAR(l,0);
        CLEAR(r,0);
        dfs(sz=1);
        CLEAR(dp,0);
        hehe1(1);
        mx=max(dp[1][1],dp[1][0]);
        hehe2(1);
        mi=min(dp[1][1],dp[1][0]);
        printf("%d %d\n",mx,mi);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: