洛谷 2585 [ZJOI2006]三色二叉树——树形dp

题目:https://www.luogu.org/problemnew/show/P2585

可以把不是绿色的记成一种。仔细一想不会有冲突。如果自己是绿色,孩子的不同颜色不会冲突;如果自己不是绿色,自己的不是绿色的孩子对于自己就像二分图一样的感觉,所以总有方案使得不区分另外两种颜色也不会有冲突。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e5+5;
int n,rt,tot,ls[N],rs[N],dp[N][2][2],p0;//是/否绿 最大/小
char ch[N];
void build(int &cr,int dep)
{
    cr=++tot;
    if(ch[p0]=='0')p0++;
    else if(ch[p0]=='1')p0++,build(ls[cr],dep+1);
    else
        p0++,build(ls[cr],dep+1),build(rs[cr],dep+1);
}
void dfs(int cr)
{
    if(!ls[cr])
    {
        dp[cr][0][0]=dp[cr][0][1]=1;
        dp[cr][1][0]=dp[cr][1][1]=0;
        return;
    }
    else if(!rs[cr])
    {
        int v=ls[cr]; dfs(v);
        dp[cr][0][0]=dp[v][1][0]+1;
        dp[cr][0][1]=dp[v][1][1]+1;
        dp[cr][1][0]=max(dp[v][0][0],dp[v][1][0]);
        dp[cr][1][1]=min(dp[v][0][1],dp[v][1][1]);
    }
    else
    {
        int Ls=ls[cr],Rs=rs[cr];
        dfs(Ls); dfs(Rs);
        dp[cr][0][0]=dp[Ls][1][0]+dp[Rs][1][0]+1;
        dp[cr][0][1]=dp[Ls][1][1]+dp[Rs][1][1]+1;
        dp[cr][1][0]=max(dp[Ls][0][0]+dp[Rs][1][0],
                         dp[Ls][1][0]+dp[Rs][0][0]);
        dp[cr][1][1]=min(dp[Ls][0][1]+dp[Rs][1][1],
                         dp[Ls][1][1]+dp[Rs][0][1]);
    }
}
int main()
{
    //freopen("TRO.IN","r",stdin);
    //freopen("TRO.OUT","w",stdout);
    scanf("%s",ch);n=strlen(ch);
    build(rt,1);
    dfs(rt);
    printf("%d %d\n",max(dp[rt][0][0],dp[rt][1][0]),
           min(dp[rt][0][1],dp[rt][1][1]));
    return 0;
}

 

posted on 2018-09-19 19:17  Narh  阅读(167)  评论(0编辑  收藏  举报

导航