CodeForces 547D Mike and Fish

CodeForces 547D Mike and Fish

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

UY6NBF.png

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;
}
posted @ 2020-07-13 20:21  LJZ_C  阅读(135)  评论(0编辑  收藏  举报