Info

グラフの連結性を判定できるデータ構造

Complexity

辺の追加 - \(O(\alpha(n))\) (\(\alpha はアッカーマン関数の逆関数\))
頂点が所属してる集合の名前の取得 - \(O(\alpha(n))\)
頂点が所属してる集合の大きさの取得 - \(O(\alpha(n))\)

Interface

UnionFind(int n) 大きさ\(n\)の頂点集合で初期化する
find(int i) 頂点\(i\)の所属してる集合の名前を返す
unite(int a, int b) \(a\)-\(b\)に辺を張る
size[find(int i)] 頂点\(i\)の所属してる集合の大きさを返す

Code

/* <UnionFind> */

struct UnionFind
{
	int n;
	std::vector<int> par,size;
	UnionFind(int sz) : n(sz), par(sz,0), size(sz,1) {
		std::iota(par.begin(),par.end(),0);
	}
	int find(int x) {
		if(par[x]==x) return x;
		return par[x] = find(par[x]);
	}
	void unite(int x, int y) {
		x=find(x);y=find(y);
		if(x==y) return;
		if(size[x]<size[y]) std::swap(x,y);
		size[x]+=size[y];
		par[y]=x;
	}
};

/* <UnionFind> */

Examples

UnionFind uf(10);
uf.unite(1,5);
uf.unite(1,3);
uf.unite(4,3);
uf.unite(5,3);
uf.unite(0,7);
std::cout << (int)(uf.find(1)==uf.find(4)) << '\n'; // 1(true)
std::cout << (int)(uf.find(0)==uf.find(4)) << '\n'; // 0(false)
std::cout << uf.size[uf.find(0)] << '\n'; // 2
uf.unite(5,7);
std::cout << (int)(uf.find(0)==uf.find(4)) << '\n'; // 1(true)
std::cout << uf.size[uf.find(0)] << '\n'; // 6