Unionf Find は競技プログラミングでは基本的なアルゴリズムなので, 説明は蟻本またはこのスライドにゆずる.
各クエリの計算量は数学的には解析が難しいが, 実用上は定数と考えて問題ない.
時間計算量: Find クエリ, Union クエリ ならし $\O (\alpha(m, n))$ ($\alpha(m, n)$ は上記で定義された増加の非常にゆるやかな関数. 実用上は定数と考えて良い.)
- class UnionFind {
- private:
- int sz;
- vector<int> par, size_;
- public:
- UnionFind(){}
- UnionFind(int node_size) : sz(node_size), par(sz), size_(sz, 1){
- iota(par.begin(), par.end(), 0);
- }
- int find(int x){
- if(par[x] == x) return x;
- else 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]) swap(x,y);
- par[y] = x;
- size_[x] += size_[y];
- }
- int size(int x){
- x = find(x);
- return size_[x];
- }
- bool same(int x,int y){
- return find(x) == find(y);
- }
- };
- class UnionFind {
- private:
- vector<int> par;
- public:
- UnionFind(){}
- UnionFind(const int node_size) : par(node_size){
- iota(par.begin(), par.end(), 0);
- }
- // 普通の path compression
- int find(int x){
- if(par[x] == x) return x;
- else return par[x] = find(par[x]);
- }
- // 実際に意味のある unite が行われたかどうかを返す.
- bool unite(int x, int y){
- int z;
- while(par[x] != par[y]){
- if(par[x] > par[y]) swap(x, y);
- z = par[x], par[x] = par[y];
- if(x == z) return true;
- x = z;
- }
- return false;
- }
- // 普通の path compression
- bool same(int x, int y){
- return find(x) == find(y);
- }
- };
AOJ : Connected Components 提出コード