Skip to content

Commit bd586ff

Browse files
author
Takanori MAEHARA
authored
Union Find with Undo
1 parent 6c4a86d commit bd586ff

1 file changed

Lines changed: 46 additions & 43 deletions

File tree

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,81 +20,84 @@ using namespace std;
2020
#define snd second
2121
#define all(c) begin(c), end(c)
2222

23-
struct undoable_union_find {
24-
vector<int> p;
25-
undoable_union_find(int n) : p(n, -1) { };
26-
vector<tuple<int,int,int>> hist;
23+
24+
struct UndoableUnionFind {
25+
vector<int> parent;
26+
vector<tuple<int,int,int>> history;
27+
UndoableUnionFind(int n) : parent(n, -1) { };
2728
bool unite(int u, int v) {
28-
if ((u = root(u)) == (v = root(v))) return false;
29-
if (p[u] > p[v]) swap(u, v);
30-
hist.push_back(make_tuple(u, v, p[v]));
31-
p[u] += p[v]; p[v] = u;
29+
u = root(u); v = root(v);
30+
if (u == v) return false;
31+
if (parent[u] > parent[v]) swap(u, v);
32+
history.push_back(make_tuple(u, v, parent[v]));
33+
parent[u] += parent[v]; parent[v] = u;
3234
return true;
3335
}
3436
void undo() {
35-
int u, v, w; tie(u, v, w) = hist.back();
36-
hist.pop_back();
37-
p[v] = w;
38-
p[u] -= p[v];
37+
int u, v, w;
38+
tie(u, v, w) = history.back();
39+
history.pop_back();
40+
parent[v] = w;
41+
parent[u] -= parent[v];
3942
}
4043
bool find(int u, int v) { return root(u) == root(v); }
41-
int root(int u) { for (; p[u] >= 0; u = p[u]); return u; }
42-
int size(int u) { return -p[root(u)]; }
44+
int root(int u) { return parent[u] < 0 ? u : parent[u] = root(parent[u]); }
45+
int size(int u) { return -parent[root(u)]; }
4346
};
4447

45-
struct offline_dynamic_connectivity {
48+
49+
struct OfflineDynamicConnectivity {
4650
int n;
47-
undoable_union_find uf;
48-
offline_dynamic_connectivity(int n) : n(n), uf(n) { }
51+
UndoableUnionFind uf;
52+
OfflineDynamicConnectivity(int n) : n(n), uf(n) { }
4953

50-
typedef pair<int,int> edge;
51-
vector<edge> query;
54+
typedef pair<int,int> Edge;
55+
vector<Edge> query;
5256
vector<int> ans;
53-
map<edge, vector<pair<int,int>>> appear;
57+
map<Edge, vector<pair<int,int>>> appear;
5458

55-
void add_edge(int u, int v) {
59+
void addEdge(int u, int v) {
5660
if (u > v) swap(u, v);
5761
appear[{u,v}].push_back({query.size(), 1<<30});
5862
}
59-
void erase_edge(int u, int v) {
63+
void eraseEdge(int u, int v) {
6064
if (u > v) swap(u, v);
6165
appear[{u,v}].back().snd = query.size();
6266
}
63-
int is_connected(int u, int v) {
67+
int isConnected(int u, int v) {
6468
query.push_back({u,v});
6569
return query.size()-1;
6670
}
67-
68-
vector<set<edge>> es;
69-
void insert(int l, int r, int k, int s, int t, edge e) {
71+
vector<set<Edge>> edges;
72+
void insert(int l, int r, int k, int s, int t, Edge e) {
7073
s = max(s, l); t = min(r, t);
7174
if (s >= t) return;
7275
if (s == l && t == r) {
73-
es[k].insert(e);
76+
edges[k].insert(e);
7477
} else {
7578
insert(l, (l+r)/2, 2*k+1, s, t, e);
7679
insert((l+r)/2, r, 2*k+2, s, t, e);
77-
if (es[2*k+1].count(e) && es[2*k+2].count(e)) {
78-
es[2*k+1].erase(e);
79-
es[2*k+2].erase(e);
80-
es[k].insert(e);
80+
if (edges[2*k+1].count(e) && edges[2*k+2].count(e)) {
81+
edges[2*k+1].erase(e);
82+
edges[2*k+2].erase(e);
83+
edges[k].insert(e);
8184
}
8285
}
8386
}
8487
void rec(int l, int r, int k) {
8588
if (l >= r) return;
86-
for (edge e: es[k]) uf.unite(e.fst, e.snd);
89+
for (Edge e: edges[k]) uf.unite(e.fst, e.snd);
8790
if (l+1 == r) {
8891
ans[l] = uf.find(query[l].fst, query[l].snd);
8992
} else {
9093
rec(l, (l+r)/2, 2*k+1);
9194
rec((l+r)/2, r, 2*k+2);
9295
}
93-
for (edge e: es[k]) uf.undo();
96+
for (Edge e: edges[k]) uf.undo();
9497
}
9598
void solve() {
9699
int q = query.size();
97-
es.resize(4*q);
100+
edges.resize(4*q);
98101
for (auto a: appear)
99102
for (auto b: a.snd)
100103
insert(0, q, 0, b.fst, b.snd, a.fst);
@@ -104,15 +107,15 @@ struct offline_dynamic_connectivity {
104107
};
105108

106109
int main() {
107-
offline_dynamic_connectivity solver(3);
108-
solver.is_connected(0,1);
109-
solver.add_edge(0,1);
110-
solver.is_connected(0,1);
111-
solver.is_connected(1,2);
112-
solver.add_edge(1,2);
113-
solver.is_connected(0,2);
114-
solver.erase_edge(0,1);
115-
solver.is_connected(0,2);
110+
OfflineDynamicConnectivity solver(3);
111+
solver.isConnected(0,1);
112+
solver.addEdge(0,1);
113+
solver.isConnected(0,1);
114+
solver.isConnected(1,2);
115+
solver.addEdge(1,2);
116+
solver.isConnected(0,2);
117+
solver.eraseEdge(0,1);
118+
solver.isConnected(0,2);
116119
solver.solve();
117120
for (int i = 0; i < solver.query.size(); ++i) {
118121
cout << solver.query[i].fst << " " << solver.query[i].snd << " " << solver.ans[i] << endl;

0 commit comments

Comments
 (0)