【Codeforces 547D】Mike and Fish

欧拉回路

题目大意:

给定二维平面上的 $n$ 个点,要求染色成红色或蓝色,使得每行每列中,两种颜色的点的个数差不超过 $1$。

求方案。

题解:

还是把横、纵坐标看成点,点当成边。要求给边定向,使得每个点的出度和入度的差不超过 $1$。

相当于欧拉路径(回路则为 $0$)。

可以新增一个 $0$,向所有度数为奇数的点(一定是偶数个)连边。则只需要找欧拉回路即可。

找欧拉回路,从任意一个点开始一直走,把边扔栈里。按照回溯时的顺序排列即为一条回路。

边走边定向即可。

时间复杂度 $O(n)$。

Code:

#include<iostream>
using namespace std;
const int N=8e5+5;
int n,vis[N],deg[N],nod,col[N],cnt,head[N];
struct edge{
    int to,nxt,id,_id;
}e[N<<1];
void dfs(int now){
    for(int&i=head[now];i;i=e[i].nxt)
        if(!vis[e[i].id]){
            --deg[now],--deg[e[i].to];
            vis[e[i].id]=1;
            if(now<=200000)col[e[i]._id]=1;
            dfs(e[i].to);
        }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;
    for(int i=1;i<=n;++i){
        int u,v;
        cin>>u>>v;
        v+=200000;
        ++nod;
        e[++cnt]=(edge){u,head[v],nod,i},head[v]=cnt;
        e[++cnt]=(edge){v,head[u],nod,i},head[u]=cnt;
        ++deg[u],++deg[v];
    }
    for(int i=1;i<=400000;++i)
        if(deg[i]&1){
            ++nod;
            e[++cnt]=(edge){0,head[i],nod,0},head[i]=cnt;
            e[++cnt]=(edge){i,head[0],nod,0},head[0]=cnt;
            ++deg[0],++deg[i];
        }
    for(int i=1;i<=400000;++i)
        if(deg[i]){
            dfs(i);
        }
    for(int i=1;i<=n;++i)
        if(col[i])cout.put('r');else cout.put('b');
    return 0;
}