zoukankan      html  css  js  c++  java
  • [Zjoi2006]三色二叉树(bzoj1864)(洛谷2585)题解

    原题地址:https://www.luogu.org/problemnew/show/P2585

    题目大意:可以把一个节点染成三种颜色,父节点和两个子节点(可以有一个)颜色不能相同。求最多(少)能有多少个点能被染成绿色


    由于是一棵树,多决策的问题,很明显的树形DP。

    关于树形DP详见https://www.cnblogs.com/lizitong/p/10020914.html

    二维状态,dp[i][j] j取0,1,2表示三种颜色。表示以这个编号为父节点取这个颜色时候有dp[i][j]个点能被染成绿色。

    DFS搜到最底,然后给叶节点附上初值。

    然后回溯更新。

    以最小值为例。

    dpmi[x][1] = min(dpmi[x][1],min(dpmi[l[x]][2]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][2])+1);
    dpmi[x][2] = min(dpmi[x][2],min(dpmi[l[x]][1]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][1]));
    dpmi[x][3] = min(dpmi[x][3],min(dpmi[l[x]][1]+dpmi[r[x]][2],dpmi[l[x]][2]+dpmi[r[x]][1]));

    如果这个点是绿色,就比较子节点分别为其他两种颜色的大小,然后+1

    如果这个点是其他颜色,就比较这两个点子节点分别是另外两种颜色和的大小。

    最后输出父节点的最大(小)状态。

    分别用l和r数组存左右儿子。

    细节较多,上代码。

    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cstring>
    #define N 500005
    using namespace std;
    char c[N];
    struct edge
    {
        int to;
        int nxt;
        int from;    
    }eg[N];
    int head[N];
    int cnt = 1;
    int ct = 1;
    int dpma[N][4];
    int dpmi[N][4];
    int l[N];
    int r[N];
    void add(int x,int y)
    {
        eg[cnt].to = y;
        eg[cnt].nxt = head[x];
        eg[cnt].from = x;
        head[x] = cnt++;
    }
    void buildtree(int x)
    {
        if(c[x]=='2')
        {
            add(x,++ct);
            l[x] = ct;
            buildtree(ct);
            add(x,++ct);
            r[x] = ct;
            buildtree(ct);
        }else if(c[x]=='1')
        {
            add(x,++ct);
            l[x] = ct;
            buildtree(ct);
        }else
        {
            return ;    
        }
    }
    void dfsma(int x)
    {
        if(l[x]==0&&r[x]==0)
        {
            dpma[x][1] = 1;
            return ;
        }else
        {
            if(l[x])
            {
                dfsma(l[x]);
                dpma[x][1] = max(dpma[x][1],max(dpma[l[x]][2]+dpma[r[x]][3],dpma[l[x]][3]+dpma[r[x]][2])+1);
                dpma[x][2] = max(dpma[x][2],max(dpma[l[x]][1]+dpma[r[x]][3],dpma[l[x]][3]+dpma[r[x]][1]));
                dpma[x][3] = max(dpma[x][3],max(dpma[l[x]][1]+dpma[r[x]][2],dpma[l[x]][2]+dpma[r[x]][1]));
            }
            if(r[x])
            {
                dfsma(r[x]);
                dpma[x][1] = max(dpma[x][1],max(dpma[l[x]][2]+dpma[r[x]][3],dpma[l[x]][3]+dpma[r[x]][2])+1);
                dpma[x][2] = max(dpma[x][2],max(dpma[l[x]][1]+dpma[r[x]][3],dpma[l[x]][3]+dpma[r[x]][1]));
                dpma[x][3] = max(dpma[x][3],max(dpma[l[x]][1]+dpma[r[x]][2],dpma[l[x]][2]+dpma[r[x]][1]));
            }
        }
    }
    void dfsmi(int x)
    {
        if(l[x]==0&&r[x]==0)
        {
            dpmi[x][1] = 1;
            dpmi[x][2] = 0;
            dpmi[x][3] = 0;
            return ;
        }else
        {
            if(l[x])
            {
                dfsmi(l[x]);
                dpmi[x][1] = min(dpmi[x][1],min(dpmi[l[x]][2]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][2])+1);
                dpmi[x][2] = min(dpmi[x][2],min(dpmi[l[x]][1]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][1]));
                dpmi[x][3] = min(dpmi[x][3],min(dpmi[l[x]][1]+dpmi[r[x]][2],dpmi[l[x]][2]+dpmi[r[x]][1]));
            }
            if(r[x])
            {
                dfsmi(r[x]);
                dpmi[x][1] = min(dpmi[x][1],min(dpmi[l[x]][2]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][2])+1);
                dpmi[x][2] = min(dpmi[x][2],min(dpmi[l[x]][1]+dpmi[r[x]][3],dpmi[l[x]][3]+dpmi[r[x]][1]));
                dpmi[x][3] = min(dpmi[x][3],min(dpmi[l[x]][1]+dpmi[r[x]][2],dpmi[l[x]][2]+dpmi[r[x]][1]));
            }
        }
    }
    int main()
    {
        scanf("%s",c+1);
        buildtree(1);
        memset(dpmi,0x3f,sizeof(dpmi));
        dpmi[0][1] = 0;
        dpmi[0][2] = 0;
        dpmi[0][3] = 0;
        dfsma(1);
        dfsmi(1);
        printf("%d ",max(max(dpma[1][1],dpma[1][2]),dpma[1][3]));
        printf("%d",min(min(dpmi[1][1],dpmi[1][2]),dpmi[1][3]));    
    }
  • 相关阅读:
    [tp3.2.1]sql查询语句(一)
    [crunch bang]在Crunch Bang安装和设置fcitx(小企鹅输入法)
    [tp3.2.1]大D构建模型
    [tp3.2.1]数据模型
    [tp3.2.1]开启URL(重写模式),省略URL中的index.php
    [tp3.2.1]让默认页面: 加载Home模块的Index控制器;而让admin.php默认去加载Admin模块的Adminc控制器.
    [JAVA]在linux中设置JDK环境,ZendStudio,Eclipse
    [fedora21]给fedora21安装fcitx输入法
    Software--Architecture--Design DataAccess 数据访问
    leetcode--Algorithm--Array_Part 1 Easy- 566 Reshape the Matrix
  • 原文地址:https://www.cnblogs.com/lizitong/p/10020984.html
Copyright © 2011-2022 走看看