[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])); }