[bzoj2932][POI1999]树的染色问题

被百度搜到的题解(论文?)坑了。

写的那玩意好像石乐志。。。


Description

一棵二叉树采用以下规则描述:

1.如果一个节点度数为0,则仅用一个元素“0”来描述它。

2.如果一个节点度数为1,则对它的描述以“1”开头,后面接着对它的孩子的描述。

3.如果一个节点度数为2,则对它的描述以“2”开头,后面接着的首先是它的左孩子的描述,然后是右孩子的描述。

在树中每一个节点必须被着为红色、绿色或蓝色。然而,我们必须遵循如下规定:

1.根点和它的孩子不能有相同的颜色。

2.如果一个节点有两个孩子,那么这两个节点必定有两个不同的颜色。

有多少个节点可以被着为绿色呢?

任务

写一个程序:

1.读取对一棵树的描述。

2.计算可以被着为绿色的节点的最大值和最小值。

3.把结果输出

Input

首行是由一个字符串组成(不长于10000字符),它是对一棵树的描述。

Output

首行两个用空格隔开的整数,它们分别表示可以被着为绿色的节点的最大和最小数目。

Sample Input

1122002010

Sample Output

5 2


其实很傻的一道题。一看AC数和Submit数就知道了。

简单树dp即可。代码十分工整且难看。。。

#include<bits/stdc++.h>
#define L t[u].ls
#define R t[u].rs
using namespace std;
const int mxn=10010;
inline int read(){
    int r=0,f=1;char c=getchar();
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){r=r*10+c-‘0‘;c=getchar();}
    return r*f;
}
int n,c=1;
char s[mxn];
struct Node{
    int ls,rs;
}t[mxn];
void dfs1(int u){
    if(s[u]==‘0‘){
        t[u].ls=t[u].rs=-1;
    }
    else if(s[u]==‘1‘){
        c++;t[u].ls=c;
        dfs1(c);
        t[u].rs=-1;
    }
    else{
        c++;t[u].ls=c;
        dfs1(c);
        c++;t[u].rs=c;
        dfs1(c);
    }
}
void init(){
    scanf("%s",s+1);
    n=strlen(s+1);
    dfs1(1);
}
int f[mxn][3],g[mxn][3];
void dfs2(int u){
    f[u][0]=g[u][0]=1;
    f[u][1]=g[u][1]=0;
    f[u][2]=g[u][2]=0;
    if(s[u]==‘0‘)return;
    dfs2(L);
    if(!~R){
        f[u][0]+=max(f[L][1],f[L][2]);
        f[u][1]+=max(f[L][0],f[L][2]);
        f[u][2]+=max(f[L][0],f[L][1]);
        g[u][0]+=min(g[L][1],g[L][2]);
        g[u][1]+=min(g[L][0],g[L][2]);
        g[u][2]+=min(g[L][0],g[L][1]);
    }
    else{
        dfs2(R);
        f[u][0]+=max(f[L][1]+f[R][2],f[L][2]+f[R][1]);
        f[u][1]+=max(f[L][0]+f[R][2],f[L][2]+f[R][0]);
        f[u][2]+=max(f[L][0]+f[R][1],f[L][1]+f[R][0]);
        g[u][0]+=min(g[L][1]+g[R][2],g[L][2]+g[R][1]);
        g[u][1]+=min(g[L][0]+g[R][2],g[L][2]+g[R][0]);
        g[u][2]+=min(g[L][0]+g[R][1],g[L][1]+g[R][0]);
    }
}
int main(){
    init();
    dfs2(1);
    cout<<max(f[1][0],max(f[1][1],f[1][2]))<<‘ ‘<<min(g[1][0],min(g[1][1],g[1][2]));
}
时间: 2024-10-11 12:02:12

[bzoj2932][POI1999]树的染色问题的相关文章

HDU3974 Assign the task(多叉树转换为线段+线段树区间染色)

题目大意:有n个人,给你他们的关系(老板和员工),没有直属上司的人就是整个公司的领导者,这意味着n个人形成一棵树(多叉树).当一个人被分配工作时他会让他的下属也做同样的工作(并且立即停止手头正在做的工作),题目会询问你其中某个人正在做的工作. 解题思路:其实从"一个人分配他的下属做一样的工作"这里就可以看出来了,这相当于让一块区间的人都做一样的事,就是线段树区间染色问题.但不能使用线段树,要先将多叉树铺展开,将节点映射到线段上.把每个人的管理区段找出来(把属于同一个人管的放一起,上司放

POJ 2528 Mayor&#39;s posters(线段树区间染色+离散化或倒序更新)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59239   Accepted: 17157 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

codevs 1191 树轴染色 线段树区间定值,求和

codevs 1191 树轴染色 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1191/ Description 在一条数轴上有N个点,分别是1-N.一开始所有的点都被染成黑色.接着我们进行M次操作,第i次操作将[Li,Ri]这些点染成白色.请输出每个操作执行后剩余黑色点的个数. Input 输入一行为N和M.下面M行每行两个数Li.Ri Output 输出M行,为每次操作后剩余黑色点的个数.

SDOI2017 树点染色

\[SDOI2017 树点染色\] 题目描述 Bob 有一棵 $ n $ 个点的有根树,其中 $ 1 $ 号点是根节点.Bob 在每个节点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是,这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob 可能会进行这几种操作: $ 1 ?x $,把点 $ x $ 到根节点的路径上的所有的点染上一种没有用过的新颜色: $ 2 ?x ?y $,求 $ x $ 到 $ y $ 的路径的权值: $ 3 ?x $,在以 $ x $ 为根的子树中选择

ZOJ 1610 线段树区间染色

给长度8000米的板,对其中区间染色,问最后能看到的颜色,和该颜色一共出现了几段 线段覆盖法 数据比较水   也可以暴力水过 线段树: #include "stdio.h" #include "string.h" struct node { int l,r,c; }data[40010]; int color[8011]; void build(int l,int r,int k) { int mid; data[k].l=l; data[k].r=r; data[

cf804C(树_dfs染色)

题目链接: http://codeforces.com/problemset/problem/804/C 题意: 有一颗含有 n 个顶点的树, 第 i 个顶点上有 k 个冰激凌, 每个冰激凌的种类为 si . 现在要给所有定点上的冰激凌染色 , 要求相同种类的冰激凌染相同的颜色, 并且同一个顶点上的冰激凌要求染不同颜色. 注意: 同一个顶点中不会出现相同的冰激凌 思路: dfs染色 首先因该考虑最多需要多少中颜色, 然后再考虑怎么染色. 对于一种冰激凌, 如果确定了其染什么颜色, 那么在后面其他

经典模型——并查集解决区间/树链染色问题

蒟蒻的第一篇blog 模型背景: 已知一个长度为n的序列,开始时序列的每一个元素都没有颜色(0),现进行m次操作,第i次操作将一段区间[l,r]中还未被染色的点(即a[i]=0的点)染成颜色i.问m次操作后这个区间长什么样子,并将它输出来. 数据规模约定:对于100%的数据,n,m<=10^6 问题解决 我会nm暴力! 对于每一个操作i,暴力扫描[l,r],染色,最后输出. ※期望得分:10. 并查集!没想到吧 用并查集来维护从节点i往后的区间[i,n]中第一个0出现的位置,也就是i之后第一个还

[HIHO1079]离散化(线段树、染色)

题目链接:http://hihocoder.com/problemset/problem/1079 MD坑爹,线段查询的时候左闭右开.插完挨个点找一遍扔set里,注意没染色的情况. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define lson l, m, rt << 1 5 #define rson m + 1, r, rt << 1 | 1 6 const int maxn = 200100; 7

TyvjOJ题目 P1473 校门外的树3(线段树区间染色种类数不覆盖)

P1473 校门外的树3 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的-- 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作: K=1,读入l,r表示在l~r之间种上的一种树 K=2,读入l,r表示询问l~r之间能见到多少种树 (l,r>0) 输入格式 第一行n,m表示道路总长为n,共有m个操作 接下来m行为m个操作 输出格式 对于每个k=