[luogu2585 ZJOI2006] 三色二叉树 (树形dp)

传送门

Description

Input

输入文件名:TRO.IN
输入文件仅有一行,不超过500000个字符,表示一个二叉树序列。

Output

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

Sample Input

1122002010

Sample Output

5 2

Code:

//By Menteur_Hxy
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ls nd[x][0]
#define rs nd[x][1]
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;

const int N=500010;
int tot=1;
int nd[N][2],f[N][3],g[N][3];

void build(int x) {
    char c=getchar();
    if(c=='1'||c=='2') nd[x][0]=++tot,build(tot);
    if(c=='2') nd[x][1]=++tot,build(tot);
    if(c=='0') f[x][2]=g[x][2]=1;
}

void dfs(int x) {
    if(ls) {
        dfs(ls);
        if(rs) {
            dfs(rs);
            f[x][0]=min(f[ls][1]+f[rs][2],f[ls][2]+f[rs][1]);
            f[x][1]=min(f[ls][0]+f[rs][2],f[ls][2]+f[rs][0]);
            f[x][2]=min(f[ls][0]+f[rs][1]+1,f[ls][1]+f[rs][0]+1);
            g[x][0]=max(g[ls][1]+g[rs][2],g[ls][2]+g[rs][1]);
            g[x][1]=max(g[ls][0]+g[rs][2],g[ls][2]+g[rs][0]);
            g[x][2]=max(g[ls][0]+g[rs][1]+1,g[ls][1]+g[rs][0]+1);
        } else {
            f[x][0]=min(f[ls][1],f[ls][2]);
            f[x][1]=min(f[ls][0],f[ls][2]);
            f[x][2]=min(f[ls][0],f[ls][1])+1;
            g[x][0]=max(g[ls][1],g[ls][2]);
            g[x][1]=max(g[ls][0],g[ls][2]);
            g[x][2]=max(g[ls][0],g[ls][1])+1;
        }
    }
}

int main() {
    build(1);
    dfs(1);
    int maxn=max(g[1][0],max(g[1][1],g[1][2]));
    int minn=min(f[1][0],min(f[1][1],f[1][2]));
    printf("%d %d",maxn,minn);
    return 0;
}

PS:写几道简单的树形dp qwq

猜你喜欢

转载自www.cnblogs.com/Menteur-Hxy/p/9343166.html