把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF547D】Mike and Fish(二分图染色)

点此看题面

  • 给定\(n\)个整点,你需要把每个点染成红色或蓝色。
  • 要求同行或同列两种颜色点数相差不超过\(1\),求一种合法方案。
  • \(n\le2\times10^5\)

二分图染色

考虑对于同一行或同一列的点,我们任意让它们两两配对(如果剩下某一个则不管),强制配对的两点颜色相反,显然可以满足条件。

然后发现这是一张二分图,黑白染色的方案必然存在。

于是就做完了?

代码:\(O(n)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200000
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n;vector<int> A[N+5],B[N+5];vector<int>::iterator ti,tj;
int ee,c[N+5],lnk[N+5];struct edge {int to,nxt;}e[4*N+5];
I void Col(CI x) {for(RI i=lnk[x];i;i=e[i].nxt) !~c[e[i].to]&&(c[e[i].to]=c[x]^1,Col(e[i].to),0);}//黑白染色
int main()

	RI i,x,y;for(scanf("%d",&n),i=1;i<=n;++i)
		scanf("%d%d",&x,&y),A[x].push_back(i),B[y].push_back(i);//存到每行/每列对应的vector里
	for(i=1;i<=N;++i) if(A[i].size())
	{
		ti=tj=A[i].begin(),A[i].size()&1&&(++ti,++tj,0);//个数为奇数就抛弃第一个
		W(ti!=A[i].end()) ++tj,add(*ti,*tj),add(*tj,*ti),++ti,++ti,++tj;//任意两两配对
	}
	for(i=1;i<=N;++i) if(B[i].size())
	{
		ti=tj=B[i].begin(),B[i].size()&1&&(++ti,++tj,0);//个数为奇数就抛弃第一个
		W(ti!=B[i].end()) ++tj,add(*ti,*tj),add(*tj,*ti),++ti,++ti,++tj;//任意两两配对
	}
	for(memset(c,-1,sizeof(c)),i=1;i<=n;++i)
		!~c[i]&&(c[i]=1,Col(i),0),putchar(c[i]?'r':'b');return 0;
}
posted @ 2020-11-18 15:09  TheLostWeak  阅读(92)  评论(0编辑  收藏  举报