AC通道:http://codevs.cn/problem/2462/
[分析]
一看,就知道这是一个基本的树形动规题。
设f[i][j]表示i节点颜色为j时,以它为根节点的二叉树的绿色节点的数量的最大值。
记lchild为i的左儿子,rchild为i的右儿子,很容易得到,
要求最小值也同理。
下面我给出复杂版的代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; struct Node{ int lchild,rchild; Node(){lchild=rchild=-1;} }; int cnt=1,K=-1; char s[500100]; Node l[500100]; int f1[500100][10]; int f2[501000][10]; inline int Max(int x,int y){ return x>y?x:y; } inline int Min(int x,int y){ return x<y?x:y; } void make(int now){ K++; if(s[K]=='0'){ l[now].lchild=l[now].rchild=-1; return; } if(s[K]=='1'){ l[now].lchild=++cnt; l[now].rchild=-1; make(cnt); return; } l[now].lchild=++cnt; make(cnt); l[now].rchild=++cnt; make(cnt); } #define lson l[now].lchild #define rson l[now].rchild void dfs(int now){ if(now==-1)return; dfs(rson); dfs(lson); if(lson==-1&&rson==-1){ f1[now][1]=1,f1[now][2]=0,f1[now][3]=0; f2[now][1]=1,f2[now][2]=0,f2[now][3]=0; } else if(lson!=-1&&rson==-1){ f1[now][1]=Max(f1[lson][2],f1[lson][3])+1; f1[now][2]=Max(f1[lson][1],f1[lson][3]); f1[now][3]=Max(f1[lson][1],f1[lson][2]); f2[now][1]=Min(f2[lson][2],f2[lson][3])+1; f2[now][2]=Min(f2[lson][1],f2[lson][3]); f2[now][3]=Min(f2[lson][1],f2[lson][2]); } else if(lson!=-1&&rson!=-1){ f1[now][1]=Max(f1[lson][2]+f1[rson][3],f1[lson][3]+f1[rson][2])+1; f1[now][2]=Max(f1[lson][1]+f1[rson][3],f1[lson][3]+f1[rson][1]); f1[now][3]=Max(f1[lson][1]+f1[rson][2],f1[lson][2]+f1[rson][1]); f2[now][1]=Min(f2[lson][2]+f2[rson][3],f2[lson][3]+f2[rson][2])+1; f2[now][2]=Min(f2[lson][1]+f2[rson][3],f2[lson][3]+f2[rson][1]); f2[now][3]=Min(f2[lson][1]+f2[rson][2],f2[lson][2]+f2[rson][1]); } } int main(){ freopen("tro.in","r",stdin); freopen("tro.out","w",stdout); memset(f2,125/2,sizeof f2); memset(f1,-1,sizeof f1); scanf("%s",s); make(1); dfs(1); printf("%d %d",Max(Max(f1[1][1],f1[1][2]),f1[1][3]),Min(Min(f2[1][1],f2[1][2]),f2[1][3])); return 0; }