$\newcommand{\O}{\mathrm{O}}$ My Algorithm : kopricky アルゴリズムライブラリ

kopricky アルゴリズムライブラリ

Union Find

コードについての説明(個人的メモ)

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);
    }
};

verify 用の問題

AOJ : Connected Components 提出コード