BZOJ_1864_[Zjoi2006]三色二叉树_树形DP
题意:
分析:递归建树,然后DP,从子节点转移。
注意到红色和蓝色没有区别,因为我们可以将红蓝互换而方案是相同的。这样的话我们只需要知道当前节点是否为绿色即可。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define N 500050 6 int lson[N],rson[N],cnt,n; 7 int f[N][2],g[N][2],h[N][2]; 8 void build(int x) 9 { 10 char s=getchar(); 11 if(s==‘0‘)return ; 12 lson[x]=++cnt;build(lson[x]); 13 if(s==‘2‘) 14 { 15 rson[x]=++cnt;build(rson[x]); 16 } 17 } 18 void dfs(int x) 19 { 20 int u=lson[x],v=rson[x]; 21 if(u==0&&v==0) 22 { 23 f[x][0]=f[x][1]=1; 24 return ; 25 } 26 dfs(u); 27 if(v) 28 { 29 dfs(v); 30 f[x][0]=max(g[u][0]+h[v][0],g[v][0]+h[u][0])+1; 31 g[x][0]=max(f[u][0]+h[v][0],f[v][0]+h[u][0]); 32 h[x][0]=max(f[u][0]+g[v][0],f[v][0]+g[u][0]); 33 f[x][1]=min(g[u][1]+h[v][1],g[v][1]+h[u][1])+1; 34 g[x][1]=min(f[u][1]+h[v][1],f[v][1]+h[u][1]); 35 h[x][1]=min(f[u][1]+g[v][1],f[v][1]+g[u][1]); 36 } 37 else 38 { 39 f[x][0]=max(g[u][0],h[u][0])+1; 40 h[x][0]=max(f[u][0],g[u][0]); 41 g[x][0]=max(f[u][0],h[u][0]); 42 f[x][1]=min(g[u][1],h[u][1])+1; 43 h[x][1]=min(f[u][1],g[u][1]); 44 g[x][1]=min(f[u][1],h[u][1]); 45 } 46 } 47 int main() 48 { 49 cnt=1; 50 build(1); 51 dfs(1); 52 printf("%d %d",max(max(f[1][0],g[1][0]),h[1][0]),min(min(f[1][1],g[1][1]),h[1][1])); 53 }