P2585 [ZJOI2006]三色二叉树

题目

难得自己独立想出来并一次过的题目!!!后来翻了下题解自己似乎写复杂了()

首先,染绿色这东西不用管,只要用三种颜色然后最后让最大或最小的那个颜色是绿色即可。

一看题,这递归建树挺 ex 的。定义 f[0/1/2][x] 表示 x 子树内的颜色 0/1/2 的数量。转移了一下,发现不行。

再加一维,f[0/1/2][0/1/2][x] 第一维表示 x 点染的颜色,第二维表示统计 x 子树内的哪种颜色。大力转移即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<code-pre class="code-pre" id="pre-FDdcQW"><code-line class="line-numbers-rows"></code-line>#include <cstdio>
<code-line class="line-numbers-rows"></code-line>#include <algorithm>
<code-line class="line-numbers-rows"></code-line>#include <iostream>
<code-line class="line-numbers-rows"></code-line>#include <cstring>
<code-line class="line-numbers-rows"></code-line>#include <vector>
<code-line class="line-numbers-rows"></code-line>#include <cmath>
<code-line class="line-numbers-rows"></code-line>#include <queue>
<code-line class="line-numbers-rows"></code-line>#include <map>
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>#define ll long long
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>using namespace std;
<code-line class="line-numbers-rows"></code-line>int rd() {
<code-line class="line-numbers-rows"></code-line>   int f=1,sum=0; char ch=getchar();
<code-line class="line-numbers-rows"></code-line>   while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
<code-line class="line-numbers-rows"></code-line>   while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
<code-line class="line-numbers-rows"></code-line>   return sum*f;
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>ll lrd() {
<code-line class="line-numbers-rows"></code-line>   ll f=1,sum=0; char ch=getchar();
<code-line class="line-numbers-rows"></code-line>   while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
<code-line class="line-numbers-rows"></code-line>   while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
<code-line class="line-numbers-rows"></code-line>   return sum*f;
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>#define int ll
<code-line class="line-numbers-rows"></code-line>#define max(A,B) (A>B?A:B)
<code-line class="line-numbers-rows"></code-line>#define min(A,B) (A>B?B:A)
<code-line class="line-numbers-rows"></code-line>const int N=(int)(5e5+5);
<code-line class="line-numbers-rows"></code-line>struct edge {
<code-line class="line-numbers-rows"></code-line>   int nex,to;
<code-line class="line-numbers-rows"></code-line>}e[N<<1];
<code-line class="line-numbers-rows"></code-line>char str[N];
<code-line class="line-numbers-rows"></code-line>int head[N],cnt,tot,n,f[3][3][N]; //第一维它自己染什么颜色
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>void add_edge(int x,int y) {
<code-line class="line-numbers-rows"></code-line>   e[++cnt].nex=head[x]; e[cnt].to=y; head[x]=cnt;
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>void init(int x) {
<code-line class="line-numbers-rows"></code-line>   if(str[x]=='0'||x>n) return ;
<code-line class="line-numbers-rows"></code-line>   if(str[x]=='2') {
<code-line class="line-numbers-rows"></code-line>       int pre=tot;
<code-line class="line-numbers-rows"></code-line>       add_edge(tot,tot+1),add_edge(tot+1,tot),++tot; 
<code-line class="line-numbers-rows"></code-line>       init(x+1); add_edge(pre,tot+1),add_edge(tot+1,pre),++tot;
<code-line class="line-numbers-rows"></code-line>       init(x+tot-pre);
<code-line class="line-numbers-rows"></code-line>   } else {
<code-line class="line-numbers-rows"></code-line>       add_edge(tot,tot+1); add_edge(tot+1,tot); ++tot; init(x+1);
<code-line class="line-numbers-rows"></code-line>   }
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>void dfs1(int x,int ff) {
<code-line class="line-numbers-rows"></code-line>   int num=0; //cout<<x<<" "<<ff<<endl;
<code-line class="line-numbers-rows"></code-line>   for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>       int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>       dfs1(y,x); ++num;
<code-line class="line-numbers-rows"></code-line>   }
<code-line class="line-numbers-rows"></code-line>   if(!num) {
<code-line class="line-numbers-rows"></code-line>       f[0][0][x]=f[1][1][x]=f[2][2][x]=1;
<code-line class="line-numbers-rows"></code-line>   } else if(num==1) {
<code-line class="line-numbers-rows"></code-line>       for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>           int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>           f[0][0][x]+=1+max(f[1][0][y],f[2][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[0][1][x]+=max(f[1][1][y],f[2][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[0][2][x]+=max(f[1][2][y],f[2][2][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][0][x]+=max(f[0][0][y],f[2][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][1][x]+=1+max(f[0][1][y],f[2][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][2][x]+=max(f[0][2][y],f[2][2][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][0][x]+=max(f[0][0][y],f[1][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][1][x]+=max(f[0][1][y],f[1][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][2][x]+=1+max(f[0][2][y],f[1][2][y]);
<code-line class="line-numbers-rows"></code-line>       }
<code-line class="line-numbers-rows"></code-line>   } else {
<code-line class="line-numbers-rows"></code-line>       int ls=0,rs;
<code-line class="line-numbers-rows"></code-line>       for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>           int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>           if(!ls) ls=y; else rs=y;
<code-line class="line-numbers-rows"></code-line>       }
<code-line class="line-numbers-rows"></code-line>       f[0][0][x]+=1+max(f[1][0][ls]+f[2][0][rs],f[1][0][rs]+f[2][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[0][1][x]+=max(f[1][1][ls]+f[2][1][rs],f[1][1][rs]+f[2][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[0][2][x]+=max(f[1][2][ls]+f[2][2][rs],f[1][2][rs]+f[2][2][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][0][x]+=max(f[0][0][ls]+f[2][0][rs],f[0][0][rs]+f[2][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][1][x]+=1+max(f[0][1][ls]+f[2][1][rs],f[0][1][rs]+f[2][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][2][x]+=max(f[0][2][ls]+f[2][2][rs],f[0][2][rs]+f[2][2][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][0][x]+=max(f[0][0][ls]+f[1][0][rs],f[0][0][rs]+f[1][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][1][x]+=max(f[0][1][ls]+f[1][1][rs],f[0][1][rs]+f[1][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][2][x]+=1+max(f[0][2][ls]+f[1][2][rs],f[0][2][rs]+f[1][2][ls]);
<code-line class="line-numbers-rows"></code-line>   }
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>void dfs2(int x,int ff) {
<code-line class="line-numbers-rows"></code-line>   int num=0; //cout<<x<<" "<<ff<<endl;
<code-line class="line-numbers-rows"></code-line>   for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>       int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>       dfs2(y,x); ++num;
<code-line class="line-numbers-rows"></code-line>   }
<code-line class="line-numbers-rows"></code-line>   if(!num) {
<code-line class="line-numbers-rows"></code-line>       for(int i=0;i<3;i++) for(int j=0;j<3;j++) f[i][j][x]=0;
<code-line class="line-numbers-rows"></code-line>       f[0][0][x]=f[1][1][x]=f[2][2][x]=1;
<code-line class="line-numbers-rows"></code-line>   } else if(num==1) {
<code-line class="line-numbers-rows"></code-line>       for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>           int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>           f[0][0][x]+=1+min(f[1][0][y],f[2][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[0][1][x]+=min(f[1][1][y],f[2][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[0][2][x]+=min(f[1][2][y],f[2][2][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][0][x]+=min(f[0][0][y],f[2][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][1][x]+=1+min(f[0][1][y],f[2][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[1][2][x]+=min(f[0][2][y],f[2][2][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][0][x]+=min(f[0][0][y],f[1][0][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][1][x]+=min(f[0][1][y],f[1][1][y]);
<code-line class="line-numbers-rows"></code-line>           f[2][2][x]+=1+min(f[0][2][y],f[1][2][y]);
<code-line class="line-numbers-rows"></code-line>       }
<code-line class="line-numbers-rows"></code-line>   } else {
<code-line class="line-numbers-rows"></code-line>       int ls=0,rs;
<code-line class="line-numbers-rows"></code-line>       for(int i=head[x];i;i=e[i].nex) {
<code-line class="line-numbers-rows"></code-line>           int y=e[i].to; if(y==ff) continue;
<code-line class="line-numbers-rows"></code-line>           if(!ls) ls=y; else rs=y;
<code-line class="line-numbers-rows"></code-line>       }
<code-line class="line-numbers-rows"></code-line>       f[0][0][x]+=1+min(f[1][0][ls]+f[2][0][rs],f[1][0][rs]+f[2][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[0][1][x]+=min(f[1][1][ls]+f[2][1][rs],f[1][1][rs]+f[2][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[0][2][x]+=min(f[1][2][ls]+f[2][2][rs],f[1][2][rs]+f[2][2][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][0][x]+=min(f[0][0][ls]+f[2][0][rs],f[0][0][rs]+f[2][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][1][x]+=1+min(f[0][1][ls]+f[2][1][rs],f[0][1][rs]+f[2][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[1][2][x]+=min(f[0][2][ls]+f[2][2][rs],f[0][2][rs]+f[2][2][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][0][x]+=min(f[0][0][ls]+f[1][0][rs],f[0][0][rs]+f[1][0][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][1][x]+=min(f[0][1][ls]+f[1][1][rs],f[0][1][rs]+f[1][1][ls]);
<code-line class="line-numbers-rows"></code-line>       f[2][2][x]+=1+min(f[0][2][ls]+f[1][2][rs],f[0][2][rs]+f[1][2][ls]);
<code-line class="line-numbers-rows"></code-line>   }
<code-line class="line-numbers-rows"></code-line>}
<code-line class="line-numbers-rows"></code-line>
<code-line class="line-numbers-rows"></code-line>signed main() {
<code-line class="line-numbers-rows"></code-line>   scanf("%s",str+1); n=strlen(str+1);
<code-line class="line-numbers-rows"></code-line>   tot=1; init(1);
<code-line class="line-numbers-rows"></code-line>   dfs1(1,0); int ans1=0,ans2=2e18; for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans1=max(ans1,f[i][j][1]);
<code-line class="line-numbers-rows"></code-line>   memset(f,0,sizeof(f));
<code-line class="line-numbers-rows"></code-line>   dfs2(1,0); for(int i=0;i<3;i++) for(int j=0;j<3;j++) ans2=min(ans2,f[i][j][1]);
<code-line class="line-numbers-rows"></code-line>   printf("%lld %lld",ans1,ans2); return 0;
<code-line class="line-numbers-rows"></code-line>}
</code-pre>

  


__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15177092.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(39)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示