每日一题 P2585 [ZJOI2006]三色二叉树 树形dp
思路挺简单的一道蓝色题目,枚举当前点的颜色与儿子颜色做转移
其实可以直接在字符串上dfs,但是怕麻烦出错还是把他先按照常规建成了我熟悉的图 代码如下
#include <bits/stdc++.h>
#define int long long
#define endl "\n"
#define MAXN 1000005
using namespace std;
struct EDGE
{
int to,next;
} edge[MAXN];
int head[MAXN],ptr;
void add_edge(int u,int v)
{
edge[++ptr].to=v;
edge[ptr].next=head[u];
head[u]=ptr;
}
void add(int a,int b)
{
add_edge(a,b);
add_edge(b,a);
}
int Rmax[MAXN],Gmax[MAXN],Bmax[MAXN];
int Rmin[MAXN],Gmin[MAXN],Bmin[MAXN];
string s;
int ptrn;
void dfs1()
{
int now=++ptrn;
if(s[now]=='0')
{
Rmax[now]=Rmin[now]=Bmax[now]=Bmin[now]=0;
Gmax[now]=Gmin[now]=1;
return;
}
if(s[now]=='2')
{
add(now,ptrn+1);
dfs1();
}
add(now,ptrn+1);
dfs1();
}
void dfs2(int now,int fa)
{
int cnt=0,son[2];
for(int p=head[now]; p; p=edge[p].next)
{
int to=edge[p].to;
if(to==fa)continue;
son[cnt++]=to;
dfs2(to,now);
}
if(cnt==1)
{
Rmax[now]=max(Gmax[son[0]],Bmax[son[0]]);
Gmax[now]=max(Rmax[son[0]],Bmax[son[0]])+1;
Bmax[now]=max(Gmax[son[0]],Rmax[son[0]]);
Rmin[now]=min(Gmin[son[0]],Bmin[son[0]]);
Gmin[now]=min(Rmin[son[0]],Bmin[son[0]])+1;
Bmin[now]=min(Gmin[son[0]],Rmin[son[0]]);
}
else if(cnt==2)
{
for(int i=0; i<=1; i++)
{
Rmax[now]=max(Gmax[son[!i]]+Bmax[son[i]],Rmax[now]);
Gmax[now]=max(Rmax[son[!i]]+Bmax[son[i]],Gmax[now]);
Bmax[now]=max(Gmax[son[!i]]+Rmax[son[i]],Bmax[now]);
Rmin[now]=min(Gmin[son[!i]]+Bmin[son[i]],Rmin[now]);
Gmin[now]=min(Rmin[son[!i]]+Bmin[son[i]],Gmin[now]);
Bmin[now]=min(Gmin[son[!i]]+Rmin[son[i]],Bmin[now]);
}
Gmax[now]++,Gmin[now]++;
}
}
signed main()
{
memset(Rmin,0x3f,sizeof(Rmin));
memset(Gmin,0x3f,sizeof(Gmin));
memset(Bmin,0x3f,sizeof(Bmin));
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>s;
s=' '+s;
dfs1();
dfs2(1,1);
cout<<max(max(Rmax[1],Gmax[1]),Bmax[1])<<' '<<min(min(Rmin[1],Gmin[1]),Bmin[1]);
}