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;
}
View Code

 

posted @ 2018-10-25 17:41  CzxingcHen  阅读(386)  评论(0编辑  收藏  举报