codeforces #547D Mike and Fish 欧拉回路

题目大意:给定平面上的n个点,要求将每个点染成红色/蓝色,使得每行/每列的红色点数和蓝色点数之差 1

将每一个横坐标/纵坐标看做一个点,每个点看做一条连接两个坐标的边
现在我们要将每条边染色使得每个点连接的所有边中两种颜色之差 1

首先找到度数为奇数的点 这样的点一定有偶数个
将度数为奇数的点两两配对连边,这样所有点的度数就都是偶数了
然后对于每个连通块,任选一个初始度数为奇数的点(不存在则任选一个度数为偶数的点),求一条欧拉回路(如果起始点初始度数为奇数则要求先遍历新连接的边),然后将路径上的边红蓝染色即可

为什么这样做是对的呢?
考虑一条欧拉回路,染色后除了起始点外每个点连出的红色边和蓝色边数量都是相同的
而对于起始点,欧拉回路的第一条边和最后一条边染上的颜色可能是相同的
那么如果起始点的初始度数为奇数,由于我先遍历了新连接的边,因此即使第一条边和最后一条边颜色相同也没关系
如果起始点的初始度数为偶数,那么这个连通块是一个二分图,第一条边和最后一条边的颜色一定不同
因此这个做法是对的

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 400400
using namespace std;
struct abcd{
    int to,num,next;
    bool ban;
}table[800800];
int head[M],tot=1;
int n;
int degree[M],stack[M],top;
bool v[M];
char ans[M];
void Assert(bool flag)
{
    if(!flag)
    {
        puts("Fuck♂You!");
        exit(0);
    }   
}
void Add(int x,int y,int z)
{
    table[++tot].to=y;
    table[tot].num=z;
    table[tot].next=head[x];
    head[x]=tot;
}
void DFS(int x)
{
    int i;
    v[x]=true;
    while(head[x])
    {
        i=head[x];
        head[x]=table[i].next;
        if(table[i].ban)
            continue;
        table[i^1].ban=true;
        DFS(table[i].to);
        stack[++top]=table[i].num;
    }
}
int main()
{
    int i,x,y;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);y+=200000;
        Add(x,y,i),Add(y,x,i);
        degree[x]++;degree[y]++;
    }
    static int a[M],tot;
    for(i=1;i<=400000;i++)
        if(degree[i]&1)
            a[++tot]=i;
    for(i=1;i<=tot;i+=2)
    {
        Add(a[i],a[i+1],0);
        Add(a[i+1],a[i],0);
    }
    for(i=1;i<=tot;i++)
        if(!v[a[i]])
        {
            DFS(a[i]);
            bool flag=false;
            while(top)
            {
                flag^=1;
                if(stack[top])
                {
                    //Assert(!ans[stack[top]]);
                    ans[stack[top]]=flag?'r':'b';
                }
                stack[top--]=0;
            }
        }
    for(i=1;i<=400000;i++)
        if(!v[i])
        {
            DFS(i);
            bool flag=false;
            while(top)
            {
                flag^=1;
                if(stack[top])
                {
                    //Assert(!ans[stack[top]]);
                    ans[stack[top]]=flag?'r':'b';
                }
                stack[top--]=0;
            }
        }
    //Assert(strlen(ans+1)==n);
    puts(ans+1);
    return 0;
}

你可能感兴趣的:(DFS,codeforces,欧拉回路)