---
# System prepended metadata

title: Disjoint Set / Union Find Template
tags: [algorithm template, Union Find, c++]

---

# Disjoint Set / Union Find Template
###### tags: `algorithm template` `c++` `Union Find`

## C++
```cpp=
class UnionFind {
public:
    UnionFind(int size) : root(size), rank(size) {
        for (int i = 0; i < size; i++) {
            root[i] = i;
            rank[i] = 1;
        }
    }

    int find(int x) {
        if (x == root[x]) {
            return x;
        }
        return root[x] = find(root[x]);
    }

    void unionSet(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX != rootY) {
            if (rank[rootX] > rank[rootY]) {
                root[rootY] = root[rootX];
            } else if (rank[rootX] < rank[rootY]) {
                root[rootX] = root[rootY];
            } else {
                root[rootY] = root[rootX];
                rank[rootX] += 1;
            }
        }
    }

    bool isConnected(int x, int y) {
        return find(x) == find(y);
    }
private:
    vector<int> root;
    vector<int> rank;
};
```
## Python
```python=
class UnionFind:
    def __init__(self, size):
        self.root = [i for i in range(size)]
        self.rank = [1] * size

    def find(self, x):
        if x == self.root[x]:
            return x
        self.root[x] = self.find(self.root[x])
        return self.root[x]

    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)
        if rootX != rootY:
            if self.rank[rootX] > self.rank[rootY]:
                self.root[rootY] = rootX
            elif self.rank[rootX] < self.rank[rootY]:
                self.root[rootX] = rootY
            else:
                self.root[rootY] = rootX
                self.rank[rootX] += 1

    def is_connected(self, x, y):
        return self.find(x) == self.find(y)
```


## Related Topics
### [LC 1971. Find if Path Exists in Graph](https://hackmd.io/@Alone0506/rJvbF5eSC)
### [LC 721. Accounts Merge](https://leetcode.com/problems/accounts-merge/description/)

>### Complexity
>n = the number of vertices in the graph.
>|             | Time Complexity | Space Complexity |
>| ----------- | --------------- | ---------------- |
>| Constructor | O(n)            | O(n)             |
>| Find        | O(α(n))         | O(1)             |
>| Union       | O(α(n))         | O(1)             |
>| isConnected | O(α(n))         | O(1)             |

Note: 
 * `n` is the number of vertices in the graph. `α` refers to the `Inverse Ackermann function`. In practice, we assume it's a constant. In other words, O(α(n)) is regarded as O(1) as average.
 * When using the combination of union by rank and the path compression optimization, the `find` operation will take O(α(n)) time on average. Since `union` and `isConnected` both make calls to `find` and all other operations require constant time, `union` and `isConnected` functions will also take O(α(n)) time on average.

## Note
[Leetcode](https://leetcode.com/explore/featured/card/graph/618/disjoint-set/3843/)
[代碼隨想錄 - 并查集理论基础](https://gitee.com/programmercarl/leetcode-master/blob/master/problems/%E5%9B%BE%E8%AE%BA%E5%B9%B6%E6%9F%A5%E9%9B%86%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.md)
