Yosupo Wettbewerb E: Oh, Vertexes & Edges!

http://kcs.miz-miz.biz/contest/6/view/E

AtCoder Grand Contest 014E: Blue and Red Tree - omochan's diary

これと全く同じじゃん!と思ったけど微妙に違った。

最初辺に注目してマージテクしようと思ったが(つまりqueueに入れるのを辺にした)、これでは新たに両端が黒になった辺がqueueに入れられることはない。入出力5を見てみるとわかると思う。

なのでqueueに入れるのは新たにmergeされた点で、元のグラフで隣接している点が黒のものがあったらmergeするというのを繰り返す。

queue<int> que;
bool B[MAX_N];

struct UF {
	int par[MAX_N];
	set<int> E[MAX_N]; //edge

	int find(int x) {
		if(par[x] == x) return x;
		else return par[x] = find(par[x]);
	}

	void init(int n) {
		rep(i, 0, n) par[i] = i;
	}

	void unite(int a, int b) { //update and merge
		a = find(a);
		b = find(b);
		if(a == b) return;
		par[a] = b;
		if((int)E[a].size() > (int)E[b].size()) swap(E[a], E[b]);
		for(int w: E[a]) {
			if(E[b].count(w)) que.push(w);
			E[b].insert(w);
		}
		E[a].clear();
	}
};

int N, M;

UF U;
vector<int> E[MAX_N];

void solve() {
	cin >> N;
	string str; cin >> str;
	rep(i, 0, N) {
		if(str[i] == 'B') {
			que.push(i);
		}
	}
	U.init(N);
	cin >> M;
	rep(i, 0, M) {
		int a, b;
		cin >> a >> b; a--; b--;
		E[a].pb(b);
		E[b].pb(a);
		U.E[a].insert(b);
		U.E[b].insert(a);
	}
	while(!que.empty()) {
		int v = que.front(); que.pop();
		if(B[v]) continue;
		B[v] = true;
		for(int w: E[v]) {
			if(B[w]) U.unite(w, v);
		}
	}
	rep(i, 0, N) {
		if(B[i]) cout << "B";
		else cout << "W";
	}
	cout << "\n";
}

テストケース何個か試したけどあってるっぽいから多分あってる(適当)