zoukankan      html  css  js  c++  java
  • 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]));
    }
  • 相关阅读:
    最近这段时间
    一元多项式的
    珍藏
    运行命令大全
    Google
    Windows Live Writer插件
    Word写论文的技
    安装Windows Live Writer后Ƃ
    比尔盖茨给人
    不经意的感悟
  • 原文地址:https://www.cnblogs.com/ZUTTER/p/9340496.html
Copyright © 2011-2022 走看看