sotanishy's code snippets for competitive programming
#include "data-structure/unionfind/union_find.hpp"
Union find (disjoint set union, 素集合データ構造) は,素集合を管理するデータ構造である.
空間計算量: $O(n)$
UnionFind(int n)
n
の union find を構築する.int find(int x)
void unite(int x, int y)
bool same(int x, int y)
int size(int x)
$\alpha(x)$ は逆アッカーマン関数である.
この実装では高速化に path compression と union by size を用いている.どちらか一方だと計算量は $O(\log n)$ になるが,両方使用することで $O(\alpha(n))$ になる.path compression の代わりに path splitting や path halving,union by size の代わりに union by rank といった実装手法もあり,どれも同じ計算量を実現する.
#pragma once
#include <algorithm>
#include <vector>
class UnionFind {
public:
UnionFind() = default;
explicit UnionFind(int n) : data(n, -1) {}
int find(int x) {
if (data[x] < 0) return x;
return data[x] = find(data[x]);
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return;
if (data[x] > data[y]) std::swap(x, y);
data[x] += data[y];
data[y] = x;
}
bool same(int x, int y) { return find(x) == find(y); }
int size(int x) { return -data[find(x)]; }
private:
std::vector<int> data;
};
#line 2 "data-structure/unionfind/union_find.hpp"
#include <algorithm>
#include <vector>
class UnionFind {
public:
UnionFind() = default;
explicit UnionFind(int n) : data(n, -1) {}
int find(int x) {
if (data[x] < 0) return x;
return data[x] = find(data[x]);
}
void unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) return;
if (data[x] > data[y]) std::swap(x, y);
data[x] += data[y];
data[y] = x;
}
bool same(int x, int y) { return find(x) == find(y); }
int size(int x) { return -data[find(x)]; }
private:
std::vector<int> data;
};