CodeForces - 547D: Mike and Fish (转化为欧拉回路)(优化dfs稠密图)(定向问题)
As everyone knows, bears love fish. But Mike is a strange bear; He hates fish! The even more strange thing about him is he has an infinite number of blue and red fish.
He has marked n distinct points in the plane. i-th point is point (xi, yi). He wants to put exactly one fish in each of these points such that the difference between the number of red fish and the blue fish on each horizontal or vertical line is at most 1.
He can't find a way to perform that! Please help him.
Input
The first line of input contains integer n (1 ≤ n ≤ 2 × 105).
The next n lines contain the information about the points, i-th line contains two integers xi and yi (1 ≤ xi, yi ≤ 2 × 105), the i-th point coordinates.
It is guaranteed that there is at least one valid answer.
OutputPrint the answer as a sequence of n characters 'r' (for red) or 'b' (for blue) where i-th character denotes the color of the fish in the i-th point.
Examples4
1 1
1 2
2 1
2 2
brrb
3
1 1
1 2
2 1
brr
题意:给定二维坐标,求一种合法的染色情况,使得每一行的颜色差异<=1;每一列也是。
思路:想不到。(不过不是第一次见了,多校也见过)。把点转化为边,那么就是每个点的两种颜色存疑最多为1,把两种颜色看成入边和出边,则和欧拉路,欧拉回路有些联系。 把度数为1的加“虚边”,染色即可。
自己的版本:离散化; 一个连通块,最多两个奇点,如果有,找出来加边,然后dfs。
(dfs的之后需要加地址符,防止多次访问无效边,会T31
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1000010; int Laxt[maxn],Next[maxn],To[maxn],cnt,vis[maxn],ans[maxn]; int x[maxn],y[maxn],a[maxn],tot1,tot2,ind[maxn],used[maxn]; int q[maxn],top,opt; void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } void dfs(int u) { if(used[u]) return ; if(ind[u]&1) q[++top]=u; used[u]=1; for(int i=Laxt[u];i;i=Next[i]) dfs(To[i]); } void dfs1(int u,int f) { for(int &i=Laxt[u];i;i=Next[i]){ //加个地址符,防止被稠密图卡。 if(!vis[i]){ ans[i/2]=opt; vis[i]=vis[i^1]=1; dfs1(To[i],i); } } ans[f/2]=opt; opt^=1; } int main() { int N; scanf("%d",&N); rep(i,1,N) scanf("%d%d",&x[i],&y[i]); rep(i,1,N) a[++tot1]=x[i]; sort(a+1,a+tot1+1);tot1=unique(a+1,a+tot1+1)-(a+1); rep(i,1,N) x[i]=lower_bound(a+1,a+tot1+1,x[i])-a; rep(i,1,N) a[++tot2]=y[i]; sort(a+1,a+tot2+1); tot2=unique(a+1,a+tot2+1)-(a+1); rep(i,1,N) y[i]=lower_bound(a+1,a+tot2+1,y[i])-a; cnt=1; rep(i,1,N) { add(x[i],y[i]+tot1); add(y[i]+tot1,x[i]); ind[x[i]]++; ind[y[i]+tot1]++; } rep(i,1,tot1+tot2) { if(!used[i]){ top=0; dfs(i); rep(i,1,top){ add(q[i],q[i+1]); add(q[i+1],q[i]); i++; } opt=0; if(top) dfs1(q[1],0); else dfs1(i,0); } } rep(i,1,N) putchar(ans[i]?'b':'r'); return 0; }
看了std:不离散化;而且任意的奇点偶可以加边,效果不变。
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; int Laxt[maxn],Next[maxn],To[maxn],cnt=1,vis[maxn],ans[maxn]; int x[maxn],y[maxn],a[maxn],tot1,tot2,ind[maxn]; int q[maxn],top,opt; inline char gc(){ static char buf[1<<16],*S,*T; if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;} return *S++; } inline int read(){ int x=0,f=1;char ch=gc(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f; } void add(int u,int v) { Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; } void dfs(int u) { for(int &i=Laxt[u];i;i=Next[i]){ if(!vis[i]&&!vis[i^1]){ vis[i]=1; dfs(To[i]); } } } int main() { int N; scanf("%d",&N); rep(i,1,N) x[i]=read(),y[i]=read()+2e5; rep(i,1,N) { add(x[i],y[i]); add(y[i],x[i]); ind[x[i]]++; ind[y[i]]++; } int lst=0; rep(i,1,4e5){ if(ind[i]&1){ if(lst) add(lst,i),add(i,lst),lst=0; else lst=i; } } rep(i,1,4e5) if(ind[i])dfs(i); rep(i,1,N) putchar(vis[i<<1]?'b':'r'); return 0; }