Disjoint Set Union
A live trace of the classic DSU with path compression and union by rank.
Every find lights its path to the root, then flattens it; every unite
hangs the shorter tree under the taller one. Watch the parent[] and rnk[]
arrays move in lockstep with the forest.
Tip: unite the same pair twice — the second call returns false.
struct DSU { vector<int> parent, rnk; DSU(int n) : parent(n), rnk(n, 0) { iota(parent.begin(), parent.end(), 0); } int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); // path compression } bool unite(int a, int b) { // false if already joined a = find(a); b = find(b); if (a == b) return false; if (rnk[a] < rnk[b]) swap(a, b); parent[b] = a; if (rnk[a] == rnk[b]) rnk[a]++; return true; } bool connected(int a, int b) { return find(a) == find(b); } };