DISJOINT-SET(7)Personal Notes

Disjoint Set

Authors: bLueriVerLHR

并查集,适合集合并操作的数据结构。

template <typename value_t>
    requires std::unsigned_integral<value_t>
class disjoint_set {

public:
    disjoint_set(size_t capacity)
    : father_(capacity), rank_(capacity, 0)
    {
        assert(capacity > 0
            && capacity - 1 <= std::numeric_limits<value_t>::max());
        // set all members belongs to themselves
        std::iota(father_.begin(), father_.end(), value_t{0});
    }

    auto
    find(value_t x)
    -> value_t {
        assert(x < father_.size());

        value_t root = x;
        while (father_[root] != root) {
            root = father_[root];
        }

        while (father_[x] != root) {
            value_t next = father_[x];
            father_[x] = root;
            x = next;
        }
        return root;
    }

    auto
    merge(value_t x, value_t y)
    -> bool {
        assert(x < father_.size());
        assert(y < father_.size());

        x = find(x);
        y = find(y);

        if (x == y) return false;
        if (rank_[x] < rank_[y]) std::swap(x, y);
        else if (rank_[x] == rank_[y]) rank_[x] += 1;

        father_[y] = x;
        return true;
    }

    auto
    size()
    -> size_t {
        return father_.size();
    }

private:
    std::vector<value_t> father_;
    std::vector<value_t> rank_;
};