把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

树形Dp-二叉树(tree)

题目描述

从前有一棵二叉树,我们用如下方式来表示这棵二叉树。
(1)如果一个节点没有儿子,我们用“0”来表示他。
(2)如果一个节点有一个儿子,我们对它的表示以“1”开头,后面接对它儿子的表示。
(3)如果一个节点有两个儿子,我们对它的表示以“2”开头,后面先接对它左儿子的
表示,后接对它右儿子的表示。
KJDH十分贪玩,将这棵树染了色,KJDH又十分聪明,它染色又很有规则:每个节点不
能和它的孩子有相同的颜色,如果一个节点有两个孩子,那么这两个孩子也不能有相同的颜
色。
由于这个树年代久远了,所以我们看不清每个节点的颜色了,但我们知道KJDH只染了
红黄白三种颜色。我们想知道这棵树最多和最少有多少个节点是白色的。
 

输入

输入文件名为tree.in。
输入文件只有一行,一个字符串,只有“0”,“1”,“2”组成,表示这
棵树的结构。
 

输出

输出文件名为tree.out。
输出文件包含两个用空格隔开的数,分别表示白色节点的最多和最少数量。
 

       样例输入1                     样例输出1

   200             1 1

       样例输入2                     样例输出2

1122002010         5 2

Solution:
容易看出是树形Dp,且属于那种比较简单的树形Dp

由于要处理两个小问题,我们设f[i][0/1/2](0->白,1->红,2—>黄)来表示以i为根的子树最多有几个白色节点,

g[i][0/1/2]则表示最小的情况

首先我们要处理读入的问题,这里我采用了递归的方式,

因为这里的节点其实是按照先序的方式来读入的,所以不断递归儿子到底后返回编号记入

之后就是转移了,按照先序遍历的顺序来转移,也就是至下而上,转移方程其实抠抠脚就可以出来了:

f[i][0]=max{f[u][1]+f[v][2],f[u][2]+f[v][1]}+1
//u、v表示左右儿子的编号,最后+1是为i节点自己为白色所以要比填其他颜色多1
f[i][1]=max{f[u][0]+f[v][2],f[u][2]+f[v][0]}
f[i][2]=max{f[u][1]+f[v][0],f[u][0]+f[v][1]}
最后把f[1][0],f[1][1],f[1][2]三个拿起来最大就是答案
g的转移和结果同理,把max改min即可。

Code:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int inf=500050;
 4 struct Node{
 5     int fa;
 6     int son[2];
 7 }Tree[inf];
 8 char Str[inf];
 9 int f[inf][3],g[inf][3],tot,Y;
10 void Dfs(int pos){
11     for(int i=0;i<=1;i++){
12         if(!Tree[pos].son[i]) break;
13         Dfs(Tree[pos].son[i]);
14     }
15     f[pos][0]=max(f[Tree[pos].son[0]][1]+f[Tree[pos].son[1]][2],f[Tree[pos].son[0]][2]+f[Tree[pos].son[1]][1])+1;
16     f[pos][1]=max(f[Tree[pos].son[0]][0]+f[Tree[pos].son[1]][2],f[Tree[pos].son[0]][2]+f[Tree[pos].son[1]][0]);
17     f[pos][2]=max(f[Tree[pos].son[0]][1]+f[Tree[pos].son[1]][0],f[Tree[pos].son[0]][0]+f[Tree[pos].son[1]][1]);
18     g[pos][0]=min(g[Tree[pos].son[0]][1]+g[Tree[pos].son[1]][2],g[Tree[pos].son[0]][2]+g[Tree[pos].son[1]][1])+1;
19     g[pos][1]=min(g[Tree[pos].son[0]][0]+g[Tree[pos].son[1]][2],g[Tree[pos].son[0]][2]+g[Tree[pos].son[1]][0]);
20     g[pos][2]=min(g[Tree[pos].son[0]][1]+g[Tree[pos].son[1]][0],g[Tree[pos].son[0]][0]+g[Tree[pos].son[1]][1]);
21 }
22 int In(int F){
23     Tree[++tot].fa=F;
24     int a=Str[++Y]-'0',Num=tot;
25     if(a>=1)
26         Tree[Num].son[0]=In(Num);
27     if(a>=2)
28         Tree[Num].son[1]=In(Num);
29     return Num;
30 }
31 using namespace std;
32 int main()
33 {
34     freopen("tree.in","r",stdin);
35     freopen("tree.out","w",stdout);
36     scanf("%s",Str+1);
37     In(0);
38     Dfs(1);
39     printf("%d %d",max(f[1][2],max(f[1][0],f[1][1])),min(g[1][2],min(g[1][0],g[1][1])));
40     return 0;
41 }

 

 
 
posted @ 2019-11-09 11:18  fluoce  阅读(266)  评论(1编辑  收藏  举报

Contact with me