bzoj 1864: [Zjoi2006]三色二叉树

Description

此处输入图片的描述

solution

正解:递归+树型DP
我们首先递归建树
然后考虑树型DP,我们设绿色的节点为Y,非绿色为N
我们神奇的发现:N会形成是很多条相互独立的链
也就是说 Y 的下发有两个 N,这两个N一定可以不同,因为此题是二叉树,可以手推出
所以DP状态只需表示为 \(f[i][N/Y]\)
\(f[i][Y]=f[ls][N]+f[rs][N]+1\)
\(f[i][N]=Max(f[ls][Y]+f[rs][N],f[rs][Y]+f[ls][N])\)
第二问改成Min即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=500005;
char S[N];int n,ch[N][2],t=1,cnt=0,root;
void dfs(int &x){
   x=++cnt;
   if(S[t]=='2'){
      t++;dfs(ch[x][0]);
      t++;dfs(ch[x][1]);
   }
   else if(S[t]=='1')t++,dfs(ch[x][0]);
}
int f[N],g[N];
void hxy(int x,bool t){
   if(ch[x][0])hxy(ch[x][0],t);
   if(ch[x][1])hxy(ch[x][1],t);
   int ls=ch[x][0],rs=ch[x][1];
   f[x]=g[ls]+g[rs]+1;
   if(!t)g[x]=Max(g[ls]+f[rs],f[ls]+g[rs]);
   else g[x]=Min(g[ls]+f[rs],f[ls]+g[rs]);
}
void work()
{
   scanf("%s",S+1);n=strlen(S+1);
   dfs(root);hxy(root,0);
   printf("%d ",Max(f[1],g[1]));
   hxy(root,1);
   printf("%d\n",Min(f[1],g[1]));
}

int main()
{
	work();
	return 0;
}

posted @ 2017-10-20 23:01  Hxymmm  阅读(172)  评论(0编辑  收藏  举报