서로소 집합 구조
정의 & 특징
- Disjoint Sets이란 공통 원소가 없는 두 집합을 의미.
- 서로소 부분 집합들로 나누어진 원소들의 데이터를 처리하기 위한 자료구조
- union(합집합), find(찾기) 2개의 연산으로 나뉨.
- union: 2개의 원소가 포함된 집합을 하나의 집합으로 합치는 연산
- find: 특정한 원소가 속한 집합이 어떤 집합인지 알려주는 연산
- 서로소 집합 자료구조는 union-find 자료구조라고도 불린다.
- 트리 자려구조를 이용하여 집합을 표현하는데 계산 알고리즘 방식은 아래와 같다.
- union 연산을 확인하여, 서로 연결된 두 노드 a, b를 확인한다.
- a와 b의 루트 노드 a', b'를 각각 찾는다.
- a'를 b'의 부모 노드로 설정한다. (b'가 a'를 가르키도록 한다.)
- 모든 union 연산을 처리할 때까지 1, 2, 3번 과정을 반복한다.
- 3의 과정에서 더 번호가 작은 원소가 부모 노드가 되도록 구현하는 경우가 대부분이다.
기본적인 서로소 집합 알고리즘 소스코드
def find_parent(parent, x):
if parent[x] != x:
return find_parent(parent, parent[x])
return parent[x]
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
v, e = map(int, input().split())
parent = [0] * (v + 1)
for i in range(1, v+1):
parent[i] = i
for i in range(e):
a, b = map(int, input().split())
union_parent(parent, a, b)
print('각 원소가 속한 집합: ', end='')
for i in range(1, v+1):
print(find_parent(parent, i), end=' ')
print()
print('부모 테이블: ', end='')
for i in range(1, v+1):
print(parent[i], end=' ')
시간 복잡도
- 경로 압축 방법만을 사용하며 노드의 개수가 v, 최대 v-1개의 union 연산과 m개의 find 연산이 가능하면
- 시간 복잡도는
O(V + M(1+log(2-M/V)V))
이다.
서로소 집합을 활용한 사이클 판별
무방향 그래프
내에서의 사이클 판별할 때 사용한다는 특징이 있다.
방향 그래프
에서의 사이클 여부는 DFS
를 이용하여 판별할 수 있다.
- 사이클을 판별하는 방식은 아래와 같다.
- 각 간선을 확인하며 두 노드의 루트 노드를 확인한다.
- 루트 노드가 서로 다르다면 두 노드에 대하여 union 연산을 수행한다.
- 루트 노드가 서로 같다면
사이클
이 발생한 것이다.
- 그래프에 포함되어 있는 모든 간선에 대하여 1, 2, 3번 과정을 반복한다.
서로소 집합을 활용한 사이클 판별 소스코드
def find_parent(parent, x):
if parent[x] != x:
parent[x] = find_parent(parent, parent[x])
return parent[x]
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
v, e = map(int, input().split())
parent = [0] * (v + 1)
for i in range(1, v+1):
parent[i] = i
cycle = False
for i in range(e):
a, b = map(int, input().split())
if find_parent(parent, a) == find_parent(parent, b):
cycle = True
break
else:
union_parent(parent, a, b)
if cycle:
print("사이클이 발생했습니다.")
else:
print("사이클이 발생하지 않았습니다.")
출처 & 깃허브
이것이 취업을 위한 코딩 테스트다 with python
github