zoukankan      html  css  js  c++  java
  • [BZOJ1864][CODEVS2462]三色二叉树

    题目描述 Description

    一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为“二叉树序列S”:

           |-0  表示该树没有子节点

    S = |-1S1 表示该树有一个子节点,S1为其子树的二叉树排列

           |- 2S1S2 表示该树有连个个子节点,S1、S2为其子树的二叉树排列

    你的任务是要对一棵二叉树的节点进行染色。每个节点可以被染成红色、绿色或蓝色。并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    1122002010

    样例输出 Sample Output

    5 2

    数据范围及提示 Data Size & Hint

     

    之前的一些废话:准备期末复习。

    题解:

    f(i,0)表示这个点不为绿色
    0个儿子:0
    1个儿子:max(f(s,1),f(s,0))
    2个儿子:max(f(s1,1)+f(s2,0),f(s1,0)+f(s2,2))

    f(i,1)表示这个点为绿色
    0个儿子:1
    一个儿子:f(s,0)+1
    两个儿子:f(s1,0)+f(s2,0)+1

    g(i,0)表示这个点不为绿色
    0个儿子:0
    1个儿子:min(g(s,1),g(s,0))
    2个儿子:min(g(s1,1)+g(s2,0),g(s1,0)+g(s2,2))

    f(i,1)表示这个点为绿色
    0个儿子:1
    一个儿子:g(s,0)+1
    两个儿子:g(s1,0)+g(s2,0)+1

    然后把输入转化成一颗树的话。。下面代码已经写了。

    代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> PII;
    #define mem(a,b) memset(a,b,sizeof(a))
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    const int maxn=500010;
    char s[maxn];
    int len,tot=1,f[2][maxn],g[2][maxn],l[maxn],r[maxn];
    void DP(int now)
    {
        if(tot>len)return;
        f[1][now]=1;g[1][now]=1;
        if(s[now]=='0')return;
        if(s[now]=='1')
        {
            tot++;l[now]=tot;DP(tot);
            f[0][now]+=max(f[0][l[now]],f[1][l[now]]);
            f[1][now]+=f[0][l[now]];
            g[0][now]+=min(g[0][l[now]],g[1][l[now]]);
            g[1][now]+=g[0][l[now]];
        }
        if(s[now]=='2')
        {
            tot++;l[now]=tot;DP(tot);
            tot++;r[now]=tot;DP(tot);
            f[0][now]+=max(f[1][l[now]]+f[0][r[now]],f[0][l[now]]+f[1][r[now]]);
            f[1][now]+=f[0][l[now]]+f[0][r[now]];
            g[0][now]+=min(g[1][l[now]]+g[0][r[now]],g[0][l[now]]+g[1][r[now]]);
            g[1][now]+=g[0][l[now]]+g[0][r[now]];
        }
    }
    int main()
    {
        scanf("%s",s+1);
        len=strlen(s+1);
        DP(1);
        printf("%d %d
    ",max(f[0][1],f[1][1]),min(g[0][1],g[0][1]));
        return 0;
    }
    View Code

    总结:

  • 相关阅读:
    拉格朗日乘子基本概念
    "模式识别与机器学习"读书笔记——2.3(2)
    [raw]人工智能方向调查
    Android !No Launcher activity found!错误
    [raw]ubuntu在当前目录右键打开终端
    Android, 读取大型文件报错
    Blueman Ubuntu的蓝牙管理器
    VMware下Ubuntu8.04 方向键失效的解决方法
    无线中间人攻击初探
    【经验】短接 Flash 解决二次量产金士顿 DTI G2 4GB U盘(群联PS225139)问题
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/7090898.html
Copyright © 2011-2022 走看看