1. 程式人生 > 實用技巧 >【CF547D】Mike and Fish(黑白染色)

【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;
}