Implementations
C++
// for the single array holds size and par trick
// you need a signed int as the array elem type
// since the par too must be same as the elem type
// you need int as type
// templating here is kind of wasteful
#include <vector>
class DSU {
private:
std::vector<int> par_;
public:
// all are their root and have size 1
DSU(int size) : par_(size, -1) {};
int root(int elem) {
if (par_[elem] < 0)
return elem;
return par_[elem] = root(par_[elem]);
}
void merge(int a, int b) {
if ((a = root(a)) == (b = root(b)))
return;
// aim is to keep the height small and if assume more elems = prob more
// height then you would want to attach the smaller one below the larger
// one INFO: larger one dominates
// invariant: a is larger
if (-par_[a] < -par_[b])
std::swap(a, b);
par_[a] += par_[b];
par_[b] = a;
}
};Java
import java.util.Arrays;
final class DSU {
private int[] par;
DSU(int size) {
par = new int[size];
Arrays.fill(par, -1);
}
public int root(int elem) {
if (par[elem] < 0)
return elem;
return par[elem] = root(par[elem]);
}
public void merge(int a, int b) {
if ((a = root(a)) == (b = root(b))) {
return;
}
// invariant: a is larger
if (-par[a] < -par[b]) {
// NOTE: the one liner arcane swap
a = a ^ b ^ (b = a);
}
par[a] += par[b];
par[b] = a;
}
}Notes
java swap trick
for primitive integral types only like int and long
a = a ^ b ^ ( b = a );can’t use with object references, for those you need a temp