zoukankan      html  css  js  c++  java
  • [P2585] [ZJOI2006]三色二叉树(树形dp)

    【原题】

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

    (S = egin{cases}0,表示该树没有子节点\ 1S_1,表示该树有一个节点,S_1为其子树的二叉树序列\ 2S_1S_2,表示该树由两个子节点,S_1和S_2分别表示其两个子树的二叉树序列end{cases})

    例如,下图所表示的二叉树可以用二叉树序列 (S = 21200110) 来表示。

    haha.png

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

    输入格式

    输入只有一行一个字符串 (s),表示二叉树序列。

    输出格式

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

    输入输出样例

    输入 #1

    1122002010
    

    输出 #1

    5 2
    

    说明/提示

    数据规模与约定

    对于全部的测试点,保证(1≤∣s∣≤5×10^5)(s) 中只含字符 0 1 2

    【思路】

    树形dp简单题

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <list>
    #include <map>
    #include <iostream>
    #include <iomanip>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <unordered_map>
    #include <vector>
    #define LL long long
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f
    #define PI 3.1415926535898
    #define F first
    #define S second
    #define endl '
    '
    #define lson  rt << 1
    #define rson  rt << 1 | 1
    #define f(x, y, z) for (int LL x = (y), __ = (z); x < __; ++x)
    #define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
    using namespace std;
    const int maxn = 5e5 + 7;
    const int mod = 1e9 + 7;
    
    int n, m;
    string s;
    int p = 0, cnt = 1;
    int f[maxn * 4][3], g[maxn  * 4][3];
    
    struct node
    {
    	int l, r, cnt;
    }nd[maxn * 4];
    
    int build(int nw, int pos)
    {
    	if (s[pos] == '0') nd[nw].l = nd[nw].r = -1;
    	else if (s[pos] == '1')
    	{
    		p++;
    		nd[nw].l = ++cnt;
    		build(cnt, p);
    		nd[nw].r = -1;
    	}
    	else
    	{
    		p++;
    		nd[nw].l = ++cnt;
    		build(cnt, p);
    		p++;
    		nd[nw].r = ++cnt;
    		build(cnt, p);
    	}
    	return 0;
    }
    
    int col(int nw)
    {
    	if (nd[nw].l == -1 && nd[nw].r == -1)
    	{
    		f[nw][0] = g[nw][0] = 1;
    		return 0;
    	}
    	else if(nd[nw].r == -1)
    	{
    		int v = nd[nw].l;
    		col(v);
    		f[nw][0] = max(f[v][1], f[v][2]) + 1;
    		f[nw][1] = max(f[v][0], f[v][2]);
    		f[nw][2] = max(f[v][0], f[v][1]);
    		g[nw][0] = min(g[v][1], g[v][2]) + 1;
    		g[nw][1] = min(g[v][0], g[v][2]);
    		g[nw][2] = min(g[v][0], g[v][1]);
    		return 0;
    	}
    	else
    	{
    		int l = nd[nw].l, r = nd[nw].r;
    		col(l);
    		col(r);
    		f[nw][0] = max(f[l][1] + f[r][2], f[l][2] + f[r][1]) + 1;
    		f[nw][1] = max(f[l][0] + f[r][2], f[l][2] + f[r][0]);
    		f[nw][2] = max(f[l][0] + f[r][1], f[l][1] + f[r][0]);
    		g[nw][0] = min(g[l][1] + g[r][2], g[l][2] + g[r][1]) + 1;
    		g[nw][1] = min(g[l][0] + g[r][2], g[l][2] + g[r][0]);
    		g[nw][2] = min(g[l][0] + g[r][1], g[l][1] + g[r][0]);
    		return 0;
    	}
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(0);
    	cin >> s;
    	build(1, 0);
    	col(1);
    	cout << max(f[1][0], max(f[1][1], f[1][2])) << " " << min(g[1][0], min(g[1][1], g[1][2]))<< endl;
    }
    
  • 相关阅读:
    Validation failed for one or more entities
    sql 存储过程
    SQL Server分页3种方案比拼
    case when 用法
    C#如何计算代码执行时间
    透过 Jet.OLEDB 读取 Excel里面的数据
    DataBinding?资料系结?资料绑定?
    ASP.NET的OutputCache
    我想写程序#3 之 「简单地设计自己的数据表(Table)」
    我想写程序#1 之 「先确立志向」
  • 原文地址:https://www.cnblogs.com/hfcdyp/p/13610930.html
Copyright © 2011-2022 走看看