D. Mike and Fish
http://codeforces.com/contest/547/problem/D
题意:
给定平面上n个点,将这些点染成红或者蓝色,要求每行、每列红色点与蓝色点数量的差的绝对值<=1。输出方案(保证有解)。
分析:
参考popoqqq的博客
将每行每列分别看做一个点,给定的每个点(x,y)拆成x->y的边,那么连边后的图是一个二分图。
这样我们可以将边染色,使得与每个点相连的两种颜色差<=1。
于是对于所有的欧拉回路,我们可以直接交替染色。
但是会有度数为奇数的点,这样的点一定有偶数个,我们对其两两配对连边,这样所有奇度数的点度数就都为偶数了。
对于每个连通块,选一个初始度数为奇数的点(若没有则任选度数为偶数的点),求一条欧拉回路(若是奇度数点则应先走与配对的奇度数点相连的边),将路径上的边交替染色即可。
正确性:
对于一条欧拉回路,除起点外每个点相连的红边与蓝边数是相同的。对于起点,欧拉回路的第一条边和最后一条边的颜色可能是相同的。
若起点初始度数为奇数,由于先走了与新连出的边,所以就算第一条和最后一条边的颜色相同也没关系。(同色的话由于有影响的点在同行同列,一定连通,所以整个连通块只会额外多出一条边颜色不同)。
若起点初始度数为偶数,则连通块是一个二分图,第一条和最后一条边的颜色一定不相同。
还有一种神奇的做法:AOQNRMGYXLMV,caoyi0905
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<cmath> 5 #include<iostream> 6 #include<cctype> 7 #include<set> 8 #include<vector> 9 #include<queue> 10 #include<map> 11 #define fi(s) freopen(s,"r",stdin); 12 #define fo(s) freopen(s,"w",stdout); 13 using namespace std; 14 typedef long long LL; 15 16 inline int read() { 17 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==‘-‘)f=-1; 18 for(;isdigit(ch);ch=getchar())x=x*10+ch-‘0‘;return x*f; 19 } 20 21 const int N = 400005; 22 const int D = 2e5; 23 24 struct Edge{ 25 int to, nxt, id; 26 }e[N << 1]; 27 int head[N], deg[N], A[N], sk[N], En = 1, top; 28 bool ve[N << 1], vd[N]; 29 char ans[N]; 30 31 void add_edge(int u,int v,int id) { 32 ++En; e[En].to = v, e[En].id = id, e[En].nxt = head[u]; head[u] = En; 33 ++En; e[En].to = u, e[En].id = id, e[En].nxt = head[v]; head[v] = En; 34 deg[u] ++, deg[v] ++; 35 } 36 37 void dfs(int u) { 38 vd[u] = true; 39 for (int i=head[u]; i; i=e[i].nxt) { 40 if (!ve[i]) { 41 ve[i] = ve[i ^ 1] = true; head[u] = i; 42 dfs(e[i].to); 43 sk[++top] = e[i].id; i = head[u]; 44 } 45 } 46 } 47 48 int main() { 49 int n = read(), cnt = 0; 50 for (int i=1; i<=n; ++i) { 51 int u = read(), v = read() + D; 52 add_edge(u, v, i); 53 } 54 for (int i=1; i<=(D<<1); ++i) 55 if (deg[i] & 1) A[++cnt] = i; 56 for (int i=1; i<=cnt; i+=2) 57 add_edge(A[i], A[i + 1], 0); 58 59 for (int i=1; i<=cnt; ++i) { 60 if (!vd[A[i]]) { 61 dfs(A[i]); 62 while (top) ans[sk[top]] = top & 1 ? ‘b‘ : ‘r‘, top --; 63 } 64 } 65 for (int i=1; i<=(D<<1); ++i) { 66 if (!vd[i]) { 67 dfs(i); 68 while (top) ans[sk[top]] = top & 1 ? ‘b‘ : ‘r‘, top --; 69 } 70 } 71 ans[n + 1] = ‘\0‘; 72 puts(ans + 1); 73 return 0; 74 }
原文地址:https://www.cnblogs.com/mjtcn/p/9839274.html
时间: 2024-11-06 13:02:49