CF 547 D. Mike and Fish

D. Mike and Fish

http://codeforces.com/contest/547/problem/D

题意:

  给定平面上n个点,将这些点染成红或者蓝色,要求每行、每列红色点与蓝色点数量的差的绝对值<=1。输出方案(保证有解)。

分析:

  参考popoqqq的博客

  将每行每列分别看做一个点,给定的每个点(x,y)拆成x->y的边,那么连边后的图是一个二分图。

  这样我们可以将边染色,使得与每个点相连的两种颜色差<=1。

  于是对于所有的欧拉回路,我们可以直接交替染色。

  但是会有度数为奇数的点,这样的点一定有偶数个,我们对其两两配对连边,这样所有奇度数的点度数就都为偶数了。

  对于每个连通块,选一个初始度数为奇数的点(若没有则任选度数为偶数的点),求一条欧拉回路(若是奇度数点则应先走与配对的奇度数点相连的边),将路径上的边交替染色即可。

正确性: 

  对于一条欧拉回路,除起点外每个点相连的红边与蓝边数是相同的。对于起点,欧拉回路的第一条边和最后一条边的颜色可能是相同的。

  若起点初始度数为奇数,由于先走了与新连出的边,所以就算第一条和最后一条边的颜色相同也没关系。(同色的话由于有影响的点在同行同列,一定连通,所以整个连通块只会额外多出一条边颜色不同)。

  若起点初始度数为偶数,则连通块是一个二分图,第一条和最后一条边的颜色一定不相同。

  还有一种神奇的做法:AOQNRMGYXLMVcaoyi0905

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cctype>
#include<set>
#include<vector>
#include<queue>
#include<map>
#define fi(s) freopen(s,"r",stdin);
#define fo(s) freopen(s,"w",stdout);
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
const int D = 2e5; struct Edge{
int to, nxt, id;
}e[N << ];
int head[N], deg[N], A[N], sk[N], En = , top;
bool ve[N << ], vd[N];
char ans[N]; void add_edge(int u,int v,int id) {
++En; e[En].to = v, e[En].id = id, e[En].nxt = head[u]; head[u] = En;
++En; e[En].to = u, e[En].id = id, e[En].nxt = head[v]; head[v] = En;
deg[u] ++, deg[v] ++;
} void dfs(int u) {
vd[u] = true;
for (int i=head[u]; i; i=e[i].nxt) {
if (!ve[i]) {
ve[i] = ve[i ^ ] = true; head[u] = i;
dfs(e[i].to);
sk[++top] = e[i].id; i = head[u];
}
}
} int main() {
int n = read(), cnt = ;
for (int i=; i<=n; ++i) {
int u = read(), v = read() + D;
add_edge(u, v, i);
}
for (int i=; i<=(D<<); ++i)
if (deg[i] & ) A[++cnt] = i;
for (int i=; i<=cnt; i+=)
add_edge(A[i], A[i + ], ); for (int i=; i<=cnt; ++i) {
if (!vd[A[i]]) {
dfs(A[i]);
while (top) ans[sk[top]] = top & ? 'b' : 'r', top --;
}
}
for (int i=; i<=(D<<); ++i) {
if (!vd[i]) {
dfs(i);
while (top) ans[sk[top]] = top & ? 'b' : 'r', top --;
}
}
ans[n + ] = '\0';
puts(ans + );
return ;
}
上一篇:Codeforces 247D Mike and Fish


下一篇:Codeforces 547D - Mike and Fish(欧拉回路)