CF547D Mike and Fish
欧拉回路,巧妙的解法。
发现每一个点$(x, y)$实际上是把横坐标和$x$和纵坐标$y$连一条线,然后代进去跑欧拉回路,这样里一条边对应了一个点,我们只要按照欧拉回路间隔染色即可。
注意到原图可能并不是一个完全的欧拉图,但是度数为奇数的点只可能有偶数个,我们可以在连完边之后再把度数为奇数的点两两配对连边,这样子就是一个完全的欧拉图了。
然后……这个图仍然可能不连通,所以每一个点都代进去搜一下。
思考一下这样子为什么是对的,我们从一个点开始走,如果这个点染了一个颜色,那么这个点同一行或者是同一列的点都不要再染同一个颜色了,向别的地方走的意思就是不染相同的颜色,这样子看似贪心地染一定能求出所需要地答案,欧拉回路其实就是确定了一个染色的顺序,我们只要看一看走了正反哪一条边就可以确定染色了。
时间复杂度应当是$O(n)$的,但是我还写了个离散化……
Code:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 2e5 + 5; const int inf = 1 << 30; int n, totx, toty, tot = 1, head[N << 1]; int deg[N << 1], ax[N], ay[N], col[N]; bool vis[N << 2]; struct Edge { int to, nxt; } e[N << 2]; inline void add(int from, int to) { e[++tot].to = to; e[tot].nxt = head[from]; head[from] = tot; } struct Innum { int val, id; friend bool operator < (const Innum &x, const Innum &y) { if(x.val != y.val) return x.val < y.val; else return x.id < y.id; } } in[N]; inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline void chkMax(int &x, int y) { if(y > x) x = y; } inline void discrete(int *arr, int preLen, int &nowLen) { in[0].val = -inf; for(int i = 1; i <= preLen; i++) in[i].val = arr[i], in[i].id = i; sort(in + 1, in + 1 + preLen); nowLen = 0; for(int i = 1; i <= preLen; i++) { if(in[i].val != in[i - 1].val) ++nowLen; arr[in[i].id] = nowLen; } } void dfs(int x) { for(int &i = head[x]; i; i = e[i].nxt) { int y = e[i].to, t = i; if(vis[t] || vis[t ^ 1]) continue; vis[t] = 1; dfs(y); } } int main() { read(n); for(int i = 1; i <= n; i++) read(ax[i]), read(ay[i]); /* printf("%d\n", n); for(int i = 1; i <= n; i++) printf("%d %d\n", ax[i], ay[i]); */ discrete(ax, n, totx), discrete(ay, n, toty); for(int i = 1; i <= n; i++) { add(ax[i], ay[i] + totx), add(ay[i] + totx, ax[i]); ++deg[ax[i]], ++deg[ay[i] + totx]; } int lst = 0; for(int i = 1; i <= totx + toty; i++) { if(!(deg[i] & 1)) continue; if(!lst) lst = i; else add(lst, i), add(i, lst), ++deg[i], ++deg[lst], lst = 0; } for(int i = 1; i <= totx + toty; i++) if(deg[i]) dfs(i); for(int i = 1; i <= n; i++) putchar(vis[i << 1] ? 'r' : 'b'); printf("\n"); return 0; }