• luogu P2585 [ZJOI2006]三色二叉树


    P2585 [ZJOI2006]三色二叉树

    题目描述

    输入输出格式

    输入格式:

    输入文件名:TRO.IN

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

    输出格式:

    输出文件名:TRO.OUT

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

    输入输出样例

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

    思路:

      我们只关心绿色节点的数目,而红色蓝色可以看作无色,
      但是对于一个根节点和它的两个儿子,必须有一个绿色节点
      按照树形DP的思路,我们开一个二维数组dp[Maxn][2]
      一二维分别保存:
      该树的最优数目,该根节点涂绿色与不涂绿色[1表示涂绿色,0表示不涂]
      以最大绿色数为例:
          dp[i][0]=max(dp[left[i]][1]+dp[right[i]][0],dp[left[i]][0]+dp[right[i]][1]);
      如果不涂i节点, 那么i节点的子节点一定要有一个涂, 所以要么左为1右为0, 要么左为0右为1
        即:
          dp[i][1]=dp[left[i]][0]+dp[right[i]][0]+1
      如果涂i节点,那么它的两个儿子当然都不能涂! [别忘了还需要加上1,即:统计上i节点的绿色]
      最小绿色也是一个道理,只要把max改为min即可:
          dp[i][0]=min(dp[left[i]][1]+dp[right[i]][0],dp[left[i]][0]+dp[right[i]][1]);

    坑点:

      数据范围是个大坑....应该开到10万才可以,他少打了个0....

    上代码:

    /*
    Max
    dp[i][1]=dp[left[i]][0]+dp[right[i]][0]+1 
    Min
    dp[i][0]=min(dp[left[i]][1]+dp[right[i]][0],dp[left[i]][0]+dp[right[i]][1]);
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int Maxn = 1000010;
    const int Colors = 2;
    int rt,top=0;
    int L[Maxn],R[Maxn];
    ///第一维表示第几个点,第二维表示染什么颜色 
    int dpMax[Maxn][Colors],dpMin[Maxn][Colors];
    
    int Max(int a, int b)
    {return a > b ? a : b;}
    int Min(int a, int b)
    {return a < b ? a : b;}
    
    int build() {
        top++;
        int num=top;
        int son=getchar()-'0';
        ///默认为son==0时没有孩子,son==1时只有左孩子,son==2时左右均有. 
        if(son==0) {
            L[num]=0;
            R[num]=0;
        }
        else if(son==1) {
            L[num]=build();
            R[num]=0;
        }
        else {
            L[num]=build();
            R[num]=build();
        }
        ///返回孩子编号 
        return num;
    }
    ///找较大值 
    void findMax(int u) {
        if(dpMax[L[u]][0]==-1)
            findMax(L[u]);
        if(dpMax[R[u]][0]==-1)
            findMax(R[u]);
        dpMax[u][0]=Max(dpMax[L[u]][0]+dpMax[R[u]][1],dpMax[L[u]][1]+dpMax[R[u]][0]);
        dpMax[u][1]=dpMax[L[u]][0]+dpMax[R[u]][0]+1; 
    }
    ///找较小值 
    void findMin(int u) {
        if(dpMin[L[u]][0]==-1)
            findMin(L[u]);
        if(dpMin[R[u]][0]==-1)
            findMin(R[u]);
        dpMin[u][0]=Min(dpMin[L[u]][0]+dpMin[R[u]][1],dpMin[L[u]][1]+dpMin[R[u]][0]);
        dpMin[u][1]=dpMin[L[u]][0]+dpMin[R[u]][0]+1; 
    }
    
    int main() {
        rt=build();
        memset(dpMax,-1,sizeof(dpMax));
        memset(dpMin,-1,sizeof(dpMin)); 
        ///空节点为0,便于更新 
        dpMax[0][1]=dpMax[0][0]=0;
        dpMin[0][1]=dpMin[0][0]=0;
        findMax(rt);
        findMin(rt);
        int a1=Max(dpMax[rt][0],dpMax[rt][1]),
            a2=Min(dpMin[rt][0],dpMin[rt][1]);
        printf("%d %d",a1,a2);
        return 0;
    }

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    学习进度条
    软件工程---课程设计总结
    软件工程----课程总结
    操作系统--实验四
    软件工程---阅读《构建之法》P384~391
    软件工程---阅读《构建之法》第8、9、10章读后感
    操作系统---实验三 进程调度模拟程序
    软件工程--- 阅读《构建之法》第6~7章
    转载---CSS3实现曲线阴影和翘边阴影
    转载---QRcodeJS生成二维码
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7360171.html
Copyright © 2020-2023  润新知