• [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]));    
    }
  • 相关阅读:
    持久化 轻量数据
    ObjectiveC 中 +load 与 +initialize
    对待“技术“与“管理”的想法
    springcloudalibaba之Nacos
    Docker上安装Redis
    Docker安装Minio
    基于Docker部署Nacos
    支付宝微信合单支付
    Nacos安装和配置
    windows常用软件安装和配置
  • 原文地址:https://www.cnblogs.com/lizitong/p/10020984.html
Copyright © 2020-2023  润新知