---
tags: Data Structure
title: Disjoint Sets
---
## Motivation
Design a data structure that stores a partition of a set.
With the operations of union, find, etc.
## Naive
### Way-A: Update the Set Each Element Belongs to
- Find: $O(1)$
- Make Union: $O(N)$
### Way-B: Update the Relation Between Elements
- Find: $O(N)$
- Make Union: $O(1)$
## Disjoint Sets (Union-find)
### Concept
If two elements are in the same set, then the **head** of both are the same.
### Meaning of Values
If `djs[x]` is negative, then `x` is the **head** of the set,
and `-djs[x]` is the population of the set.
Otherwise, `djs[x]` is also a member(it's usually head) of the set.
### Find
If `djs[x]` is negative, then `x` is the head of the set.
Otherwise, replace `djs[x]` with `find(djs[x])`. **(Path compression)**
### Make Union
Compare `djs[find(x)]` with `djs[find(y)]`,
adding the smaller set to the other one. **(Union by Rank)**
### Complexity
- Initiallization: $O(N)$
- Each Operation: $O(\alpha(N)),~\alpha:$ [Inverse Ackermann Function](https://en.wikipedia.org/wiki/Ackermann_function#Inverse) (nearly constant, with path compression and union by rank)
- Space: $O(N)$
### Sample Code
```cpp=
class DisjointSets {
DisjointSets(int n) : djs(n, -1) {}
int find(int x) {
if (djs[x] < 0) return x;
return djs[x] = find(djs[x]); // Path Compression
}
int population(int x) {
return -djs[find(x)];
}
void unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
// Union By Rank
if (djs[px] < djs[py]) { // population: x > y
djs[px] += djs[py];
djs[py] = px;
}
else {
djs[py] += djs[px];
djs[px] = py;
}
}
private:
vector<int> djs;
};
```