P2585 [ZJOI2006]三色二叉树

题目描述

输入输出格式

输入格式:

输入文件名:TRO.IN

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

输出格式:

输出文件名:TRO.OUT

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

输入输出样例

输入样例#1: 
1122002010
输出样例#1:
5 2

树形dp
可以发现,只要不是绿色,红色或蓝色对于答案是没有影响的。
所以题目变成:在一棵二叉树上,每个有两个儿子节点的点和他的2个儿子中一定要有一个绿色点点,相邻的两个点不能都是绿色时求绿色的最大量和最小量。
然后就是基础的树形dp啦!要注意的是这道题的建图需要一定的技巧。
#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;

int i,m,n,j,k,a[500005][4],f[500005],son[500005][2],d[500005];

int dfs(int x,int fa)
{
    scanf("%1ld",&d[x]);
    f[x]=fa;
    if(fa)
    {
        if(son[fa][0]) son[fa][1]=x;
        else son[fa][0]=x;
    }
    if(d[x]==0) return x;
    if(d[x]==2) return dfs(dfs(x+1,x)+1,x);
    return dfs(x+1,x);
}

void ddfs(int x)
{
    if(!x) return;
    if(!d[x]) 
    {
        a[x][1]=a[x][3]=1;
        return;
    }
    ddfs(son[x][0]); ddfs(son[x][1]);
    a[x][0]=max(a[son[x][0]][1]+a[son[x][1]][0],a[son[x][0]][0]+a[son[x][1]][1]);
    a[x][1]=1+a[son[x][0]][0]+a[son[x][1]][0];
    a[x][2]=min(a[son[x][0]][3]+a[son[x][1]][2],a[son[x][0]][2]+a[son[x][1]][3]);
    a[x][3]=1+a[son[x][0]][2]+a[son[x][1]][2];
}

int main()
{
    dfs(1,0);
    ddfs(1);
    printf("%d %d",max(a[1][0],a[1][1]),min(a[1][2],a[1][3]));
}

猜你喜欢

转载自www.cnblogs.com/ZUTTER/p/9340496.html