给构造题提供了一种新的思路。
如果答案占总方案数的比较大,可以考虑随机化。
例如本题,考虑随机化,难点变成判断一个方案是否可行。考虑 2-SAT,如果一个点是 \(\text{B}\),那么对于这个点的边,有一条边的另一个端点是 \(\text{W}\),那么其他两个都是 \(\text{B}\)。反之同理。跑一遍 2-SAT 即可知道随出来的这个解是否合法。
code
// Problem: E - Not Dyed by Majority (Cubic Graph)
// Contest: AtCoder - AtCoder Regular Contest 161
// URL: https://atcoder.jp/contests/arc161/tasks/arc161_e
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<int, int> pii;
const int maxn = 500100;
int n, f[maxn], head[maxn], len;
vector<int> G[maxn];
mt19937 rnd(time(NULL));
int dfn[maxn], low[maxn], times, scc[maxn], cnt, stk[maxn], top;
struct edge {
int to, next;
} edges[maxn * 10];
inline void add_edge(int u, int v) {
edges[++len].to = v;
edges[len].next = head[u];
head[u] = len;
}
void dfs(int u) {
dfn[u] = low[u] = ++times;
stk[++top] = u;
for (int i = head[u]; i; i = edges[i].next) {
int v = edges[i].to;
if (!dfn[v]) {
dfs(v);
low[u] = min(low[u], low[v]);
} else if (!scc[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++cnt;
while (1) {
int x = stk[top--];
scc[x] = cnt;
if (x == u) {
break;
}
}
}
}
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
vector<int>().swap(G[i]);
}
for (int i = 0, u, v; i < n * 3 / 2; ++i) {
scanf("%d%d", &u, &v);
G[u].pb(v);
G[v].pb(u);
}
while (1) {
for (int i = 1; i <= n; ++i) {
f[i] = rnd() & 1;
}
len = times = cnt = 0;
for (int i = 1; i <= n * 2; ++i) {
head[i] = dfn[i] = low[i] = scc[i] = 0;
}
for (int i = 1; i <= n; ++i) {
int u = G[i][0], v = G[i][1], w = G[i][2];
if (f[i]) {
add_edge(u, v + n);
add_edge(u, w + n);
add_edge(v, u + n);
add_edge(v, w + n);
add_edge(w, u + n);
add_edge(w, v + n);
} else {
add_edge(u + n, v);
add_edge(u + n, w);
add_edge(v + n, u);
add_edge(v + n, w);
add_edge(w + n, u);
add_edge(w + n, v);
}
}
for (int i = 1; i <= n * 2; ++i) {
if (!dfn[i]) {
dfs(i);
}
}
bool flag = 0;
for (int i = 1; i <= n; ++i) {
if (scc[i] == scc[i + n]) {
for (int u = 1; u <= n; ++u) {
putchar(f[u] ? 'B' : 'W');
}
putchar('\n');
flag = 1;
break;
}
}
if (flag) {
break;
}
}
}
int main() {
int T = 1;
scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
- Majority AtCoder Regular Contest Cubicmajority atcoder regular contest atcoder regular contest 165 minimization atcoder regular contest atcoder regular contest 166 atcoder regular contest degree atcoder regular contest 167 atcoder regular contest sliding atcoder regular contest 164 atcoder regular contest builder subsegments atcoder regular contest