Skip to the content.

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

Depends on

Code

#include <bits/stdc++.h>

template <typename AbelGroup> class UndoUnionFind {
    using T = typename AbelGroup::value_type;
    size_t n, num;
    std::vector<size_t> sz, parent;
    std::stack<std::pair<size_t, size_t>> sta;
    std::vector<T> value;

  public:
    UndoUnionFind() = default;
    UndoUnionFind(size_t n)
        : n(n), num(n), sz(n, 1), parent(n, 0), value(n, AbelGroup::unit()) {
        std::iota(parent.begin(), parent.end(), 0);
    }

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

    T get(size_t x) const {
        assert(0 <= x and x < n);
        if (x == parent[x])
            return value[x];
        T ret = value[x];
        while (x != parent[x]) {
            x = parent[x];
            AbelGroup::Rchop(ret, value[x]);
        }
        return ret;
    }

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

    bool merge(size_t x, size_t 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;
        AbelGroup::Rchop(value[y], AbelGroup::inverse(value[x]));
        num--;
        sta.emplace(x, y);
        return true;
    }

    void undo() {
        if (!sta.size())
            return;
        auto [x, y] = sta.top();
        sta.pop();
        sz[x] -= sz[y];
        parent[y] = y;
        AbelGroup::Rchop(value[y], value[x]);
        num++;
    }

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

    size_t count() const { return num; }
};
#line 1 "library/datastructure/unionfind/ApplyUndoUnionFind.hpp"
#include <bits/stdc++.h>

template <typename AbelGroup> class UndoUnionFind {
    using T = typename AbelGroup::value_type;
    size_t n, num;
    std::vector<size_t> sz, parent;
    std::stack<std::pair<size_t, size_t>> sta;
    std::vector<T> value;

  public:
    UndoUnionFind() = default;
    UndoUnionFind(size_t n)
        : n(n), num(n), sz(n, 1), parent(n, 0), value(n, AbelGroup::unit()) {
        std::iota(parent.begin(), parent.end(), 0);
    }

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

    T get(size_t x) const {
        assert(0 <= x and x < n);
        if (x == parent[x])
            return value[x];
        T ret = value[x];
        while (x != parent[x]) {
            x = parent[x];
            AbelGroup::Rchop(ret, value[x]);
        }
        return ret;
    }

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

    bool merge(size_t x, size_t 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;
        AbelGroup::Rchop(value[y], AbelGroup::inverse(value[x]));
        num--;
        sta.emplace(x, y);
        return true;
    }

    void undo() {
        if (!sta.size())
            return;
        auto [x, y] = sta.top();
        sta.pop();
        sz[x] -= sz[y];
        parent[y] = y;
        AbelGroup::Rchop(value[y], value[x]);
        num++;
    }

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

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