[FZU 1022] 三色二叉树/二叉树染色
Posted bit_line
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[FZU 1022] 三色二叉树/二叉树染色相关的知识,希望对你有一定的参考价值。
模拟题,当然也可以叫树形dp。
数据结构作业,所以要写一棵树,为了可读性,又手残枚举了三种颜色,所以代码显得长一些,但是整个的思路还是非常的好理解的。而且变量名也尽量取得即使长一些也是很好理解的,呵呵...
亮出15CM-->
/*
链接http://acm.fzu.edu.cn/problem.php?pid=1022
187 ms 2180KB
*/
/*********by JBer********/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
/*
树形dp,定义状态dp[i][j]表示结点i颜色为j(下面枚举对应,记0为绿色) 时可以搞到
的最大答案
转移:
dp[father][0] = maxdp[leftson][1]+1, dp[leftson][2]+1;
dp[father][1] = maxdp[leftson][0], dp[leftson][2];
dp[father[2] = maxdp[leftson][0], dp[leftson][1];
---当father只有左孩纸时
其它情况类似
初始化孩纸们的dp[][0] = 1, dp[][1] = dp[][2] = 0就可以搞了= =
*/
const int COLORTYPE = 3;
enum COLOR GREEN, RED, BLUE, NONE;
struct Node
Node* left, *right;
int maxGreen[COLORTYPE]; //maxGreen[i]该结点颜色为i时可以搞出的最大绿色结点数目
int minGreen[COLORTYPE]; //和上面差不多= =
//int tag[COLORTYPE];
Node()
left = right = NULL;
memset(maxGreen, 0, sizeof(int) * COLORTYPE);
memset(minGreen, 0, sizeof(int) * COLORTYPE);
//memset(tag, -1, sizeof(int) * COLORTYPE);
;
typedef Node* binTree;
char* build(binTree& T, char* s)
//printf("%c->%d\\n", *s, s);
if (s[0] == '0')
T = new Node();
return s + 1;
else if (s[0] == '1')
T = new Node();
return build(T->left, s + 1);
else
T = new Node();
char* p = build(T->left, s + 1);
return build(T->right, p);
int countNode(const binTree& T)
if (T == NULL)
// puts("0");
return 0;
//printf("T->left = %d, T->right = %d\\n", T->left ? 1 : 0, T->right ? 1 : 0);
return countNode(T->left) + countNode(T->right) + 1;
void Destroy(binTree& T)
if (T == NULL) return;
Destroy(T->left);
Destroy(T->right);
delete T;
void treeDP(const binTree& T)
if (T == NULL) return;
treeDP(T->left);
treeDP(T->right);
if (T->left == NULL && T->right == NULL)
T->maxGreen[GREEN] = 1, T->maxGreen[RED] = T->maxGreen[BLUE] = 0;
T->minGreen[GREEN] = 1, T->minGreen[RED] = T->minGreen[BLUE] = 0;
else if (T->left != NULL && T->right == NULL)
T->maxGreen[GREEN] = std::max(T->left->maxGreen[RED], T->left->maxGreen[BLUE]) + 1;
T->maxGreen[RED] = std::max(T->left->maxGreen[GREEN], T->left->maxGreen[BLUE]);
T->maxGreen[BLUE] = std::max(T->left->maxGreen[GREEN], T->left->maxGreen[RED]);
T->minGreen[GREEN] = std::min(T->left->minGreen[RED], T->left->minGreen[BLUE]) + 1;
T->minGreen[RED] = std::min(T->left->minGreen[GREEN], T->left->minGreen[BLUE]);
T->minGreen[BLUE] = std::min(T->left->minGreen[GREEN], T->left->minGreen[RED]);
else if (T->left == NULL && T->right != NULL)
T->maxGreen[GREEN] = std::max(T->right->maxGreen[RED], T->right->maxGreen[BLUE]) + 1;
T->maxGreen[RED] = std::max(T->right->maxGreen[GREEN], T->right->maxGreen[BLUE]);
T->maxGreen[BLUE] = std::max(T->right->maxGreen[GREEN], T->right->maxGreen[RED]);
T->minGreen[GREEN] = std::min(T->right->minGreen[RED], T->right->minGreen[BLUE]) + 1;
T->minGreen[RED] = std::min(T->right->minGreen[GREEN], T->right->minGreen[BLUE]);
T->minGreen[BLUE] = std::min(T->right->minGreen[GREEN], T->right->minGreen[RED]);
else
//equal to: T->left != NULL && T->right != NULL
//这里有一个trick,所以搞起来要注意两个子节点颜色不同的要求,转移方程作适当变化
T->maxGreen[GREEN] = std::max(T->left->maxGreen[RED] + T->right->maxGreen[BLUE], T->left->maxGreen[BLUE] + T->right->maxGreen[RED]) + 1;
T->maxGreen[RED] = std::max(T->left->maxGreen[GREEN] + T->right->maxGreen[BLUE], T->left->maxGreen[BLUE] + T->right->maxGreen[GREEN]);
T->maxGreen[BLUE] = std::max(T->left->maxGreen[GREEN] + T->right->maxGreen[RED], T->left->maxGreen[RED] + T->right->maxGreen[GREEN]);
T->minGreen[GREEN] = std::min(T->left->minGreen[RED] + T->right->minGreen[BLUE], T->left->minGreen[BLUE] + T->right->minGreen[RED]) + 1;
T->minGreen[RED] = std::min(T->left->minGreen[GREEN] + T->right->minGreen[BLUE], T->left->minGreen[BLUE] + T->right->minGreen[GREEN]);
T->minGreen[BLUE] = std::min(T->left->minGreen[GREEN] + T->right->minGreen[RED], T->left->minGreen[RED] + T->right->minGreen[GREEN]);
/*
int maxTmp = -1;
for (int i = 0; i < COLORTYPE; ++i)
if (T->maxGreen[i] > maxTmp) maxTmp = T->maxGreen[i];
printf("%d\\n", maxTmp);
*/
const int MAXLEN = 10086;
char buffer[MAXLEN];
int main()
while (~scanf(" %s", buffer))
binTree T = NULL;
build(T, buffer);
//printf("%d\\n", countNode(T));
treeDP(T);
int minAns = INT_MAX, maxAns = INT_MIN;
for (int i = 0; i < COLORTYPE; ++i)
if (T->maxGreen[i] > maxAns) maxAns = T->maxGreen[i];
if (T->minGreen[i] < minAns) minAns = T->minGreen[i];
printf("%d %d\\n", maxAns, minAns);
Destroy(T);
return 0;
/*
1122002010
5 2
*/
以上是关于[FZU 1022] 三色二叉树/二叉树染色的主要内容,如果未能解决你的问题,请参考以下文章