AtCoder Regular Contest 161

C - Dyed by Majority (Odd Tree)

题意

给定一棵树,保证每个点的度数都是奇数。对树上的结点进行黑白染色。现给出目标颜色序列,要求找到一个初始颜色序列,使得经一次操作后得到目标颜色序列。

操作定义为:对每个结点,记目标颜色为与它相邻的结点中超过半数所具有的颜色。将所有结点的颜色同时修改为目标颜色。

题解

从特殊情况入手。考虑叶子结点和它的父亲。显然,具有相同父亲的叶子结点必然有相同的目标颜色。并且它们要求父亲的初始颜色即为它们的目标颜色。而它们的初始颜色显然取与父亲的目标颜色相同更优。(因为它们没有孩子,不会对孩子产生影响)

于是我们得到了这样一个贪心策略:进行dfs。对于一个结点,如果它的子结点中两种颜色相等,那么它要求父结点的初始颜色与它的目标颜色一致。而如果它的颜色没有被子结点要求,那么就取父结点的目标颜色。

代码

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
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
vector<int> g[maxn];
char tag[maxn],ans[maxn];
bool ok=1;
void dfs(int u,int fa)
{
int cnt0=0,cnt1=0;
for(auto v:g[u])
{
if(v==fa) continue;
dfs(v,u);
if(ans[v]!=tag[u]) cnt0++;
else cnt1++;
}
if(cnt0>cnt1) ok=0;
else if(cnt0==cnt1)
{
if(!ans[fa]) ans[fa]=tag[u];
else
{
if(ans[fa]!=tag[u]) ok=0;
}
}
if(!ans[u])
{
if(fa) ans[u]=tag[fa];
else ans[u]='B';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;cin>>t;
while(t--)
{
int n;cin>>n;
ok=1;
for(int i=1;i<=n;i++) ans[i]=0,g[i].clear();
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
g[u].push_back(v),g[v].push_back(u);
}
for(int i=1;i<=n;i++) cin>>tag[i];
dfs(1,0);
if(!ok) cout<<-1<<'\n';
else
{
for(int i=1;i<=n;i++) cout<<ans[i];
cout<<'\n';
}
}
return 0;
}

D - Everywhere is Sparser than Whole (Construction)

题意

定义图的密度为边数与点数之比。要求构造一张密度为 DD 的图,满足其任意导出子图的密度均小于 DD

题解

考虑完全图,可以得到图的密度的上界 Dn12D\leq \lfloor\dfrac{n-1}{2}\rfloor。对于满足该限制的 DD,我们总可以构造出合法的图。具体做法是:将编号距离为 1,2,,D1,2,\cdots,D 的点两两连边。然后就做完了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,d;cin>>n>>d;
if(d>(n-1)/2) cout<<"No"<<'\n';
else
{
cout<<"Yes"<<'\n';
for(int i=1;i<=d;i++)
for(int j=1;j<=n;j++)
cout<<j<<' '<<(j+i-1)%n+1<<'\n';
}
return 0;
}

E - Not Dyed by Majority (Cubic Graph)

题意

给出一张图,保证每个点的度数均为 33。对图上的结点进行黑白染色。要求构造一个目标颜色序列,使得不存在一个初始颜色序列,可以经一次操作得到该目标颜色序列。

操作定义为:对每个结点,记目标颜色为与它相邻的结点中超过半数所具有的颜色。将所有结点的颜色同时修改为目标颜色。

题解

直观的感受是,很多目标颜色序列都无法得到。所以我们可以采用随机化,然后用2-sat进行检验。

代码

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
#include <bits/stdc++.h>
using namespace std;
const int maxn=50005;
vector<int> g0[maxn];
int ans[maxn];
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
int rd(int l,int r) {return rnd()%(r-l+1)+l;}
int cnt,head[2*maxn];
struct Edge
{
int to,nxt;
}e[6*maxn];
void add(int u,int v)
{
e[++cnt]={v,head[u]};
head[u]=cnt;
}
int dfn[2*maxn],low[2*maxn],dfncnt,stk[2*maxn],instk[2*maxn],tp;
int scc[2*maxn],sc;
void tarjan(int u)
{
low[u]=dfn[u]=++dfncnt,stk[++tp]=u,instk[u]=1;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instk[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
sc++;
while(stk[tp]!=u)
{
scc[stk[tp]]=sc;
instk[stk[tp]]=0;
tp--;
}
scc[stk[tp]]=sc;
instk[stk[tp]]=0;
tp--;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;cin>>t;
while(t--)
{
int n;cin>>n;
for(int i=1;i<=n;i++) g0[i].clear();
for(int i=1;i<=3*n/2;i++)
{
int u,v;cin>>u>>v;
g0[u].push_back(v),g0[v].push_back(u);
}
bool ok=0;
while(1)
{
cnt=dfncnt=tp=sc=0;
for(int i=1;i<=2*n;i++) head[i]=dfn[i]=low[i]=stk[i]=instk[i]=scc[i]=0;
for(int i=1;i<=n;i++) ans[i]=rd(0,1);
for(int i=1;i<=n;i++)
{
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
if(j!=k)
{
if(ans[i]) add(g0[i][j],g0[i][k]+n);
else add(g0[i][j]+n,g0[i][k]);
}
}
for(int i=1;i<=2*n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
{
if(scc[i]==scc[i+n])
{
ok=1;
break;
}
}
if(ok)
{
for(int i=1;i<=n;i++)
if(ans[i]) cout<<'B';
else cout<<'W';
cout<<'\n';
break;
}
}
}
return 0;
}

AtCoder Regular Contest 161
https://je3ter.github.io/2023/06/23/ACM/AtCoder Regular Contest 161/
作者
Je3ter
发布于
2023年6月23日
许可协议