Description
- 給定 \(n\) 個整點。
- 你要給每個點染成紅色或藍色。
- 要求同一水平線或垂直線上兩種顏色的數量最多相差 \(1\)。
- \(n,x_i, y_i \le 2 \times 10^5\)。
Solution
考慮給每條水平線和垂直線建一個點,對於每個整點就把它對應的兩條線連一條邊。
題目就轉化為了給每條邊定向,使得每個點入度和出度不超過 \(1\)。這是個經典的問題,由於度數為奇數的點只有偶數個,所以新建一個點和這個奇度數的點連邊,然後跑尤拉回路定向即可。
時間複雜度:\(O(n)\)。
Code
#include <bits/stdc++.h>
// #define int int64_t
const int kMaxN = 6e5 + 5;
int n;
int x[kMaxN], y[kMaxN], ans[kMaxN], cur[kMaxN];
bool vis[kMaxN], vx[kMaxN];
std::vector<std::pair<int, int>> G[kMaxN];
void dfs(int u) {
vx[u] = 1;
for (int i = cur[u]; i < (int)G[u].size(); i = cur[u]) {
auto [v, id] = G[u][i];
cur[u] = i + 1;
if (vis[id]) continue;
vis[id] = 1;
dfs(v);
if (u >= 1 && u <= 2e5 && v > 2e5) ans[id] = 0;
else if (v >= 1 && v <= 2e5 && u > 2e5) ans[id] = 1;
else assert(!u || !v);
}
}
void dickdreamer() {
std::cin >> n;
for (int i = 1; i <= n; ++i) {
std::cin >> x[i] >> y[i];
G[x[i]].emplace_back(y[i] + (int)2e5, i), G[y[i] + (int)2e5].emplace_back(x[i], i);
}
int tmp = n;
for (int i = 1; i <= 4e5; ++i)
if (G[i].size() & 1)
G[0].emplace_back(i, ++tmp), G[i].emplace_back(0, tmp);
for (int i = 0; i <= 4e5; ++i) dfs(i);
for (int i = 1; i <= n; ++i)
std::cout << (ans[i] ? 'r' : 'b');
}
int32_t main() {
#ifdef ORZXKR
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int T = 1;
// std::cin >> T;
while (T--) dickdreamer();
// std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
return 0;
}