标签:树形DP
Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
题意:给定一棵二叉树,将其染色(红,绿,蓝),其父亲节点必须和两个儿子节点染上不同的颜色,两个儿子节点也必须染不同颜色,问最多最少有多少个节点被染成绿色
分析:f[i][0]表示当前节点没染绿色的最大值 f[i][1]表示当前节点染上绿色的最大值
F[i][0]=max(f[l[x]][1]+f[r[x]][0] ,f[l[x]][0]+f[r[x]][1]);
F[i][1]=f[l[x]][0]+f[r[x]][0]+1
最小值同理
Code
#include<iostream> #include<iomanip> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) #define LL long long #define mem(x,num) memset(x,num,sizeof x) #define reg(x) for(int i=head[x];i;i=e[i].next) using namespace std; const int maxn=3e5+6; LL f[maxn][3],l[maxn],r[maxn],ans1,ans2,cnt=1; inline void read(int x) { char ch=getchar(); if(ch=='0')return; cnt++;l[x]=cnt;read(cnt); if(ch=='2'){cnt++;r[x]=cnt;read(cnt);} } void dp1(int x) { if(!x)return ; dp1(l[x]);dp1(r[x]); f[x][1]=f[l[x]][0]+f[r[x]][0]+1; f[x][0]=max(f[l[x]][0]+f[r[x]][1],f[r[x]][0]+f[l[x]][1]); } void dp2(int x) { if(!x)return; dp2(l[x]);dp2(r[x]); f[x][1]=f[l[x]][0]+f[r[x]][0]+1; f[x][0]=min(f[l[x]][0]+f[r[x]][1],f[r[x]][0]+f[l[x]][1]); } int main() { read(1); mem(f,0); dp1(1);ans1=max(f[1][1],f[1][0]); mem(f,0); dp2(1);ans2=min(f[1][1],f[1][0]); printf("%lld %lld\n",ans1,ans2); return 0; }