---
# System prepended metadata

title: Union-Find

---

# Union-Find

- Union-Find를 알기 앞서, `Disjoint Set`이라는 것을 먼저 보면, disjoint set 은 **중복되지 않은 원소를 가진 두 집합**(서로소 집합)이라고 볼 수 있다. 
- Union-Find 는 union 의 기능과 find 의 기능을 갖고 있는 자료구조라고 생각하면 된다. **union** 이 하는 기능은 두 원소를 하나의 집합으로 만드는 기능이고, **find** 는 특정 원소가 어느 집합에 속해있는지 알려주는 기능이다. 

Union
---
- union(a,b) 는 원소 a 가 속한 집합과 원소 b 가 속한 집합을 합치는 과정이다.union 을 하는 과정은 다음과 같다
    1. 원소 a 와 b의 root 를 찾는다. 각 원소의 root 를 찾아 이 두 root를 하나로 합치는 과정을 해야하므로 필요한 과정이다. 이 때, Find 기능을 사용한다. (Find의 내용은 아래에서 다룸)
    2. A 와 B 의 root 중 작은 값을 A 와 B 의 공통 root 로 설정한다. 즉, 두 집합을 하나로 합치려면 공통의 root를 가져야 하는데 이 값을 작은 값으로 일반적으로 설정한다. 
    3. 모든 원소와 집합에 대해서 union 연산을 처리할 때까지 1과 2를 반복한다.

[Union](https://velog.io/@woo0_hooo/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-union-find-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)
```python=
# 두 원소가 속한 집합을 합치기
def union_parent(parent, a, b):
    a = find_parent(parent, a)
    b = find_parent(parent, b)
    if a < b:
        parent[b] = a
    else:
        parent[a] = b
```

Find
---
- find(a) 하는 과정은 다음과 같다. 
    1. 원소 a의 부모가 자기 자신이 아니라면 (자신이 root 가 아니라면) find (parent[a]) 를 수행한다.
    2. 자기 자신이 부모가 되면 재귀 호출은 멈춘다. 
[Find](https://velog.io/@woo0_hooo/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-union-find-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)
```python=
def find_parent(parent, x):
    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
    if parent[x] != x:
        return find_parent(parent, parent[x])
    return x
```
- 여기서 find 의 과정이 비효율적으로 느껴질 수 있다. 5 -> 4 -> 3-> 2-> 1 의 관계라고 하면, 5의 root를 찾는 일은 항상 $O(N)$ 만큼의 시간이 소요된다. union/find 연산이 $M$ 횟수만큼 반복된다고 하면, 시간복잡도는 $O(NM)$ 이 된다. 이 문제를 해결하기 위해서 압축된 경로를 사용하는 것이 좋다. 
- 특별한 방법은 아니고, parent 를 저장하는 테이블에 root 를 저장하면 된다. 즉, 5의 부모는 4가 아니라 1을 저장하면 된다. 

[Find2](https://velog.io/@woo0_hooo/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-union-find-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)
```python=
# 특정 원소가 속한 집합을 찾기
def find_parent(parent, x):
    # 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
    if parent[x] != x:
        return find_parent(parent, parent[x])
    return parent[x]
```

활용 사례
---
- Union-Find는 그래프에서 $forest$를 찾기
- Kruskal's algorithm: Kruskal's algorithm 은 weight 이 가장 낮은 간선 순서대로 정렬해서 병합(union) 해나가는 방식으로 union-find 자료구조에 적합하다. 
- 무방향 그래프에서의 Cycle을 판별
- 그래프가 Bipartite인지 판별
- 문제
    - https://leetcode.com/problems/number-of-provinces/ 
    - https://leetcode.com/problems/redundant-connection/