1. 程式人生 > 實用技巧 >CodeForces 547D Mike and Fish

CodeForces 547D Mike and Fish

CodeForces 547D Mike and Fish

https://codeforces.com/contest/547/problem/D

Tutorial

https://codeforces.com/blog/entry/18126

二分圖,左右分別有\(2 \times 10^5\)個節點,一共有\(n\)條邊,將每條邊染上紅色或藍色,使得每個點相鄰的不同顏色的邊數量差絕對值小於等於1

考慮如果圖中只有偶度點,找到歐拉回路,由於是環,所以相鄰邊染不同顏色就可以不影響每個點的相鄰不同色邊差的情況下完成染色.

假如圖中有奇度點,那麼一定存在它到另一個奇度點的路徑,那麼將這條路徑找出來,相鄰邊染不同顏色,那麼只會有這兩個奇度點的差發生變化,而且由於這樣之後它們就是偶度點了,所以今後也不會變化.

具體實現可以每次找出一個奇度點\(u\),然後刪掉任意刪掉一條與它相鄰的邊\(v\),在解決掉刪掉之後的子問題後,根據\(v\)當前的差的情況選擇這條邊的顏色.因為觀察演算法過程,發現修改\(v\)的顏色比修改\(u\)的顏色更優(\(u\)之前更有可能有別的刪去的邊)

Code

#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define fi first
#define se second
using namespace std;
inline char gc() {
	return getchar();
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void rd(T &x) {
	x=0; int f=1,ch=gc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=gc();}
	x*=f;
}
const int maxn=2e5+50,maxN=4e5+50;
const int N=4e5;
int n,an[maxn];
int deg[maxN];
set<int> s[2];
set< pair<int,int> > E[maxN];
vector<int> R;
struct node {
	int u,v,id;
	node(int u=0,int v=0,int id=0):u(u),v(v),id(id){}
};
vector<node> rec;
inline void addedge(int u,int v,int id) {
	E[u].insert(make_pair(v,id));
	E[v].insert(make_pair(u,id));
}
inline void del(int u,int v,int id) {
	s[E[u].size()&1].erase(u);	
	E[u].erase(make_pair(v,id));
	s[E[u].size()&1].insert(u);
}
void dfs(int u) {
	while(E[u].size()) {
		int v=E[u].begin()->fi,id=E[u].begin()->se;
		E[u].erase(E[u].begin()),E[v].erase(make_pair(u,id));
		dfs(v);
		R.push_back(id);
	}
}
int main() {
	rd(n);
	for(int i=1;i<=n;++i) {
		int x,y; rd(x),rd(y),y+=2e5;
		addedge(x,y,i);
	}
	for(int i=1;i<=N;++i) s[E[i].size()&1].insert(i);
	while(s[1].size()) {
		int u=*s[1].begin();
		int v=E[u].begin()->fi,id=E[u].begin()->se;
		rec.push_back(node(u,v,id));
		del(u,v,id),del(v,u,id);
	}
	for(int i=1;i<=N;++i) if(E[i].size()) dfs(i);
	for(int i=0;i<R.size();++i) an[R[i]]=i&1;
	for(int i=rec.size()-1;~i;--i) {
		int u=rec[i].u,v=rec[i].v,id=rec[i].id;
		if(deg[v]>0) an[id]=0,--deg[u],--deg[v];
		else an[id]=1,++deg[u],++deg[v];
	}
	for(int i=1;i<=n;++i) printf("%c",an[i]?'r':'b');
	printf("\n");
	return 0;
}