-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathundo_unionfind.hpp
32 lines (31 loc) · 1.1 KB
/
undo_unionfind.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#pragma once
#include <numeric>
#include <stack>
#include <utility>
#include <vector>
// CUT begin
// UnionFind, able to rewind to the previous state by undo()
// Written for Educational Codeforces 62 F, although not verified yet.
struct UndoUnionFind {
using pint = std::pair<int, int>;
std::vector<int> par, cou;
std::stack<std::pair<int, pint>> history;
UndoUnionFind(int N) : par(N), cou(N, 1) { std::iota(par.begin(), par.end(), 0); }
int find(int x) const { return (par[x] == x) ? x : find(par[x]); }
bool unite(int x, int y) {
x = find(x), y = find(y);
if (cou[x] < cou[y]) std::swap(x, y);
history.emplace(y, pint(par[y], cou[x]));
return x != y ? par[y] = x, cou[x] += cou[y], true : false;
}
void undo() {
cou[par[history.top().first]] = history.top().second.second;
par[history.top().first] = history.top().second.first;
history.pop();
}
void reset() {
while (!history.empty()) undo();
}
int count(int x) const { return cou[find(x)]; }
bool same(int x, int y) const { return find(x) == find(y); }
};