正解貌似是大暴搜?
首先我们考虑这是一个二分图,建立网络流模型后很容易得出一个算法
S->行 容量为Num[X]/2;
行->列 容量为1 且要求(x,y)这个点存在
列->T 容量为Num[Y]/2
这样子跑网络流之后我们就得到了一组解
但是我们考虑输出方案
对于每一行,如果Num[X]为偶数,那么显然输出方案是正确的
但是如果Num[x]为奇数,多出的那个显然既有可能是红的也可能是蓝的
但关键是我们不能确定他是红的或者蓝的,因为他的状态也会影响对应的列
同样,列的考虑也是同理
所以我们对于残量网络,如果Num[X]或者Num[Y]是奇数,那么就连对应的容量为1的边
对残量网络在进行一次网络流,这样就可以输出方案辣
(话说网络流跑40w的点居然一点也不虚)
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<queue> #define h(i) i #define l(i) i+200000 using namespace std; const int maxn=200010; const int oo=0x7fffffff; int S,T; int n,cntx,cnty; int X[maxn],Y[maxn]; int NX[maxn],NY[maxn]; int idx[maxn],idy[maxn]; bool visx[maxn],visy[maxn]; int h[maxn<<1],cnt=1; int cur[maxn<<1]; struct edge{ int to,next,w; }G[4000010]; int vis[maxn<<1]; queue<int>Q; void add(int x,int y,int z){ ++cnt; G[cnt].to=y;G[cnt].next=h[x];G[cnt].w=z;h[x]=cnt; ++cnt; G[cnt].to=x;G[cnt].next=h[y];G[cnt].w=0;h[y]=cnt; } void read(int &num){ num=0;char ch=getchar(); while(ch<‘!‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar(); } bool BFS(){ memset(vis,-1,sizeof(vis)); Q.push(S);vis[S]=1; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=h[u];i;i=G[i].next){ int v=G[i].to; if(vis[v]==-1&&G[i].w>0){ vis[v]=vis[u]+1; Q.push(v); } } }return vis[T]!=-1; } int DFS(int x,int f){ if(x==T||f==0)return f; int w,used=0; for(int i=cur[x];i;i=G[i].next){ if(vis[G[i].to]==vis[x]+1){ w=f-used; w=DFS(G[i].to,min(w,G[i].w)); G[i].w-=w;G[i^1].w+=w; if(G[i].w>0)cur[x]=i; used+=w;if(used==f)return used; } } if(!used)vis[x]=-1; return used; } void dinic(){ while(BFS()){ for(int i=S;i<=T;++i)cur[i]=h[i]; DFS(S,oo); }return; } int main(){ read(n);S=0;T=400001; for(int i=1;i<=n;++i){ read(X[i]);read(Y[i]); NX[X[i]]++;NY[Y[i]]++; } for(int i=1;i<=n;++i)add(h(X[i]),l(Y[i]),1); for(int i=1;i<=n;++i){ if(!visx[X[i]]){ add(S,h(X[i]),NX[X[i]]>>1); visx[X[i]]=true; } if(!visy[Y[i]]){ add(l(Y[i]),T,NY[Y[i]]>>1); visy[Y[i]]=true; } } dinic(); memset(visx,false,sizeof(visx)); memset(visy,false,sizeof(visy)); for(int i=1;i<=n;++i){ if(!visx[X[i]]){ visx[X[i]]=true; if(NX[X[i]]&1)add(S,h(X[i]),1); } if(!visy[Y[i]]){ visy[Y[i]]=true; if(NY[Y[i]]&1)add(l(Y[i]),T,1); } } dinic(); for(int i=1;i<=n;++i){ if(!G[(i<<1)+1].w)printf("b"); else printf("r"); }return 0; }
时间: 2024-09-30 16:14:35