LOJ3126「COCI 2018.10」Teoretičar【分治】

二分图边染色,2-approximate。

\(L,R\le10^5,M\le5\cdot10^5\)


边染色都做过两道题了咋还不会做啊。

把 2-Coloring 那题拿过来,两种颜色分治一下,没了。

复杂度 \(O(M\log M)\)

#include<bits/stdc++.h>
#define PB emplace_back
#define fi first
#define se second
#define MP make_pair
using namespace std;
typedef pair<int, bool> pib;
const int N = 500003;
template<typename T>
void rd(T &x){
	int ch = getchar(); x = 0;
	for(;ch < '0' || ch > '9';ch = getchar());
	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
}
int n1, n2, m, ccnt, ans[N], fa[N], siz[N], mat[N];
bool val[N];
struct Node {int u, v, id;};
pib getf(int x){
	if(fa[x] == x) return MP(x, false);
	pib tp = getf(fa[x]);
	return MP(fa[x] = tp.fi, val[x] ^= tp.se);
}
void comb(int u, int v){
	pib p1 = getf(u), p2 = getf(v);
	if(p1.fi == p2.fi) return;
	if(siz[p1.fi] > siz[p2.fi]) swap(p1, p2);
	siz[p2.fi] += siz[p1.fi]; fa[p1.fi] = p2.fi;
	val[p1.fi] = (p1.se == p2.se);
}
void work(const vector<Node> &E){
	int m = E.size(); bool flg = false;
	for(const Node &e : E) mat[e.u] = mat[e.v] = -1;
	for(int i = 0;i < m;++ i){
		fa[i] = i; siz[i] = 1;
		val[i] = false;
	}
	for(int i = 0;i < m;++ i){
		int u = E[i].u, v = E[i].v;
		if(~mat[u]){
			flg = true;
			comb(mat[u], i);
			mat[u] = -1;
		} else mat[u] = i;
		if(~mat[v]){
			flg = true;
			comb(mat[v], i);
			mat[v] = -1;
		} else mat[v] = i;
	}
	if(!flg){
		++ccnt;
		for(const Node &e : E)
			ans[e.id] = ccnt;
		return;
	}
	vector<Node> E1, E2;
	for(int i = 0;i < m;++ i)
		(getf(i).se ? E2 : E1).PB(E[i]);
	work(E1); work(E2);
}
int main(){
	rd(n1); rd(n2); rd(m);
	vector<Node> E(m);
	for(int i = 0;i < m;++ i){
		rd(E[i].u); rd(E[i].v);
		E[i].v += n1; E[i].id = i;
	} work(E); printf("%d\n", ccnt);
	for(int i = 0;i < m;++ i) printf("%d\n", ans[i]);
}
posted @ 2021-06-14 15:49  mizu164  阅读(147)  评论(0编辑  收藏  举报