bzoj1864(树形DP)

1864: [Zjoi2006]三色二叉树

Time Limit: 1 Sec   Memory Limit: 64 MB
Submit: 647   Solved: 458
[ Submit][ Status][ Discuss]

Description

Input

仅有一行,不超过500000个字符,表示一个二叉树序列。

Output

输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。

Sample Input

1122002010

Sample Output

5 2



解题思路:先根据原序列构建出二叉树,然后在二叉树上进行树形DP。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
char c[510000];
int size,tt;
int fa[510000];
int dui[2][510000];
int mi[4][510000],ma[4][510000];


void dfs(int fg,int o)
 {
  ++size; fa[size]=fg; dui[o][fg]=size;
  if (c[tt]=='0') return;
    if (c[tt]=='1')
     {
      ++tt;
      dfs(size,0);
}else
 {
  int u=size;
  ++tt; dfs(u,0); 
  ++tt; dfs(u,1);
 }
 }


void dp(int o)
 {
  if (dui[0][o]==0 && dui[1][o]==0)
  {
    mi[1][o]=0;mi[2][o]=0;mi[3][o]=1;ma[1][o]=0;ma[2][o]=0;ma[3][o]=1;
  return;
}
  if (dui[0][o]!=0) dp(dui[0][o]);
  if (dui[1][o]!=0) dp(dui[1][o]);
  if (dui[1][o]==0)
  {
  mi[1][o]=min(mi[2][dui[0][o]],mi[3][dui[0][o]]); mi[2][o]=min(mi[1][dui[0][o]],mi[3][dui[0][o]]); mi[3][o]=min(mi[1][dui[0][o]],mi[2][dui[0][o]])+1;
        ma[1][o]=max(ma[2][dui[0][o]],ma[3][dui[0][o]]); ma[2][o]=max(ma[1][dui[0][o]],ma[3][dui[0][o]]); ma[3][o]=max(ma[1][dui[0][o]],ma[2][dui[0][o]])+1;
 }else
  {
  mi[1][o]=min(mi[2][dui[0][o]]+mi[3][dui[1][o]],mi[3][dui[0][o]]+mi[2][dui[1][o]]);
  mi[2][o]=min(mi[1][dui[0][o]]+mi[3][dui[1][o]],mi[3][dui[0][o]]+mi[1][dui[1][o]]);
  mi[3][o]=min(mi[2][dui[0][o]]+mi[1][dui[1][o]],mi[1][dui[0][o]]+mi[2][dui[1][o]])+1;
  ma[1][o]=max(ma[2][dui[0][o]]+ma[3][dui[1][o]],ma[3][dui[0][o]]+ma[2][dui[1][o]]);
  ma[2][o]=max(ma[3][dui[0][o]]+ma[1][dui[1][o]],ma[1][dui[0][o]]+ma[3][dui[1][o]]);
  ma[3][o]=max(ma[2][dui[0][o]]+ma[1][dui[1][o]],ma[1][dui[0][o]]+ma[2][dui[1][o]])+1;
  }
    
 }


int main()
{
scanf("%s",c+1);
tt=1; size=0;
dfs(0,0);
for (int i=1;i<=3;++i)
for (int j=1;j<=size;++j) 
 {
  mi[i][j]=10000000; ma[i][j]-100000000;
 }
dp(1);
long long ans1=max(max(ma[1][1],ma[2][1]),ma[3][1]); 
long long ans2=min(min(mi[1][1],mi[2][1]),mi[3][1]);
printf("%lld %lld",ans1,ans2);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值