![](image/logo.png)
F.A.Qs | Home | Discuss | ProblemSet | Status | Ranklist | 1 Contest | 入门OJ | ModifyUser Sakura_Lemon | Logout | 捐赠本站 |
---|
1864: [Zjoi2006]三色二叉树
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1022 Solved: 748
[ Submit][ Status][ Discuss]
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
HINT
Source
令f[i][0]表示i这个点不色,i下面的子树最多能取多少个色的点
f[i][1]表示i这个点染色,i下面的子树最多能取多少个色的点
首先考虑对于一个点,如果染色,那么根据题目所述,它的左右儿子必须染得跟它不一样所以
f[i][1]=f[r[i]][0]+f[l[i]][0]+1
然后如果这个点不染色,那么一个节点与其左右儿子必须颜色不同,枚举从左右儿子中哪一个转移过来就好了
所以
f[i][0]=max(f[l[i]][0]+f[r[i]][1],f[l[i]][1]+f[r[i]][0])
f[i][0]=min(f[l[i]][0]+f[r[i]][1],f[l[i]][1]+f[r[i]][0])
#include<iostream>
#include<cstdio>
using namespace std;
#define N 500010
int dp[N][2],l[N],r[N],root=1;
inline void read(int rt){
char ch;
if((ch=getchar())=='0')return;
l[rt]=++root;
read(root);
if(ch=='2')r[rt]=++root,read(root);
}
inline void dpf(int rt){
if(!rt)return;
dpf(r[rt]),dpf(l[rt]);
dp[rt][1]=dp[l[rt]][0]+dp[r[rt]][0]+1;
dp[rt][0]=max(dp[l[rt]][0]+dp[r[rt]][1],dp[l[rt]][1]+dp[r[rt]][0]);
}
inline void dps(int rt){
if(!rt)return;
dps(r[rt]),dps(l[rt]);
dp[rt][1]=dp[l[rt]][0]+dp[r[rt]][0]+1;
dp[rt][0]=min(dp[l[rt]][0]+dp[r[rt]][1],dp[l[rt]][1]+dp[r[rt]][0]);
}
int main(){
read(root);
dpf(1);
printf("%d ",max(dp[1][0],dp[1][1]));
for(register int i=1;i<=root;i++)dp[i][0]=dp[i][1]=0;
dps(1);
printf("%d\n",min(dp[1][0],dp[1][1]));
return 0;
}