Skip to the content.

:warning: library/datastructure/unionfind/MonoidUnionFind.hpp

Depends on

Code

template <typename AbelMonoid> class UnionFind {
    using T = typename AbelMonoid::value_type;
    int n, num;
    std::vector<int> sz, parent;
    std::vector<T> value;

  public:
    UnionFind() = default;
    UnionFind(int n)
        : n(n), num(n), sz(n, 1), parent(n), value(n, AbelMonoid::unit()) {
        std::iota(parent.begin(), parent.end(), 0);
    }
    UnionFind(const std::vector<T> &v)
        : n(v.size()), num(n), sz(n, 1), parent(n), value(v) {
        std::iota(parent.begin(), parent.end(), 0);
    }

    int leader(int x) {
        assert(0 <= x and x < n);
        return (x == parent[x] ? x : parent[x] = leader(parent[x]));
    }

    T sum(int x) { return value[leader(x)]; }

    void multiply(int x, T a) { AbelMonoid::Rchop(value[leader(x)], a); }

    bool same(int x, int y) {
        assert(0 <= x and x < n and 0 <= y and y < n);
        return leader(x) == leader(y);
    }

    bool merge(int x, int y) {
        assert(0 <= x and x < n and 0 <= y and y < n);
        x = leader(x);
        y = leader(y);
        if (x == y)
            return false;
        if (sz[x] < sz[y])
            std::swap(x, y);
        sz[x] += sz[y];
        parent[y] = x;
        AbelMonoid::Rchop(value[x], value[y]);
        num--;
        return true;
    }

    int size(const int x) {
        assert(0 <= x and x < n);
        return sz[leader(x)];
    }

    int count() const { return num; }
};
#line 1 "library/datastructure/unionfind/MonoidUnionFind.hpp"
template <typename AbelMonoid> class UnionFind {
    using T = typename AbelMonoid::value_type;
    int n, num;
    std::vector<int> sz, parent;
    std::vector<T> value;

  public:
    UnionFind() = default;
    UnionFind(int n)
        : n(n), num(n), sz(n, 1), parent(n), value(n, AbelMonoid::unit()) {
        std::iota(parent.begin(), parent.end(), 0);
    }
    UnionFind(const std::vector<T> &v)
        : n(v.size()), num(n), sz(n, 1), parent(n), value(v) {
        std::iota(parent.begin(), parent.end(), 0);
    }

    int leader(int x) {
        assert(0 <= x and x < n);
        return (x == parent[x] ? x : parent[x] = leader(parent[x]));
    }

    T sum(int x) { return value[leader(x)]; }

    void multiply(int x, T a) { AbelMonoid::Rchop(value[leader(x)], a); }

    bool same(int x, int y) {
        assert(0 <= x and x < n and 0 <= y and y < n);
        return leader(x) == leader(y);
    }

    bool merge(int x, int y) {
        assert(0 <= x and x < n and 0 <= y and y < n);
        x = leader(x);
        y = leader(y);
        if (x == y)
            return false;
        if (sz[x] < sz[y])
            std::swap(x, y);
        sz[x] += sz[y];
        parent[y] = x;
        AbelMonoid::Rchop(value[x], value[y]);
        num--;
        return true;
    }

    int size(const int x) {
        assert(0 <= x and x < n);
        return sz[leader(x)];
    }

    int count() const { return num; }
};
Back to top page