🧠 알고리즘
- 유니온 파인드 (Union-Find / Disjoint Set Union, DSU)
✔️ 동작 방식
문제 핵심 아이디어:
- 서로소 집합을 관리하며, 두 원소가 같은 집합에 속하는지 확인하거나(find) 두 집합을 합치는(union) 문제에 사용.
- 초기화:
- pt_list[i] = i로 각 원소를 자기 자신이 부모가 되도록 설정.
- find 연산 (_find_pt):
- 특정 원소가 속한 집합의 대표자를 찾음.
- 경로 압축(Path Compression) 사용: 탐색 과정에서 만나는 모든 원소의 부모를 대표자로 바로 갱신하여 이후 연산을 빠르게 함.
- 반복문 기반 구현으로 재귀 깊이 초과 문제 방지.
- union 연산 (_union):
- 두 원소가 속한 집합을 합침.
- 대표자 비교 후 작은 쪽으로 부모를 갱신.
- 이렇게 하면 트리의 높이를 얕게 유지 가능.
- 연산 처리 (_main):
- 입력으로 주어진 m개의 연산을 순차 처리.
- type == 0: 두 원소를 같은 집합으로 합침 (_union)
- type == 1: 두 원소가 같은 집합인지 확인 (_find_pt)
- 결과를 YES 또는 NO로 리스트에 저장 후 한 번에 출력.
🧾 코드
import sys
def _find_pt(num):
while pt_list[num] != num:
pt_list[num] = pt_list[pt_list[num]] # 경로 압축
num = pt_list[num]
return pt_list[num]
def _union(x, y):
x_root, y_root = _find_pt(x), _find_pt(y)
if x_root > y_root:
pt_list[x_root] = y_root
else:
pt_list[y_root] = x_root
def _main(n, m):
answer = []
for _ in range(m):
type, a, b = map(int, sys.stdin.readline().rstrip().split())
a_root, b_root = _find_pt(a), _find_pt(b)
if type == 0: # 합치기
_union(a_root, b_root)
else:
answer.append("YES") if a_root == b_root else answer.append("NO")
return '\n'.join(answer)
n, m = map(int, sys.stdin.readline().rstrip().split())
pt_list = [i for i in range(n + 1)]
print(_main(n, m))
⏱️ 시간 복잡도
for _ in range(m) : m번 순회 ( 선형 시간 복잡도 )
# 유니온 파인드 - 경로 압축 시간 연산 ( 상수 시간 )
_find_pt(num)
_union(x, y)
해당 알고리즘 시간 복잡도 : 선형 시간 복잡도 ( O(n) )'코딩테스트 파이썬 > 백준' 카테고리의 다른 글
| 1로 만들기 ( 1463 번 ) (0) | 2025.10.24 |
|---|---|
| 여행 가자 ( 1976 번 ) (0) | 2025.10.23 |
| 스타트와 링크 ( 14889 번 ) (0) | 2025.10.23 |
| K번째 수 ( 1300 번 ) (0) | 2025.10.22 |
| 가장 긴 증가하는 부분 수열 2 ( 12015 번 ) (0) | 2025.10.21 |