Description
Input
仅有一行,不超过500000个字符,表示一个二叉树序列。
Output
输出文件也只有一行,包含两个数,依次表示最多和最少有多少个点能够被染成绿色。
Sample Input
1122002010
Sample Output
5 2
题意:给定一颗有根树,可以选择染成绿色或者染成其他颜色,父亲节点相同的节点要求颜色不同,求最后最多/少有几个绿色节点
可以发现这个蓝色和红色没有用,开个数组记录一下是否染成绿色就好了,方程也很好推啊T T,第一次写树形dp也
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> using namespace std; #define ll long long #define inf 0x7fffffff inline int read() { int x=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int cnt,l[500000],r[500000]; void get(int x) { char ch=getchar(); if(ch==‘0‘) return; cnt++;l[x]=cnt;get(l[x]); if(ch==‘2‘){cnt++;r[x]=cnt;get(r[x]);} } int f[500000][2]; void dp(int x) { if(!x) return; dp(l[x]);dp(r[x]); f[x][1]=f[l[x]][0]+f[r[x]][0]+1; f[x][0]=max(f[l[x]][1]+f[r[x]][0],f[l[x]][0]+f[r[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]][1]+f[r[x]][0],f[l[x]][0]+f[r[x]][1]); } int ans1,ans2; int main() { cnt=1;get(1); dp(1);ans1=max(f[1][1],f[1][0]); memset(f,0,sizeof(f)); dp2(1);ans2=min(f[1][1],f[1][0]); printf("%d %d\\n",ans1,ans2); }