-
Union-Find 알고리즘Algorithms in Python/notes 2021. 2. 7. 08:30
Union-Find (서로소 집합) 자료구조
서로소 부분 집합들로 나누어진 원소들의 데이터를 처리하기 위한 자료구조
• union(합집합) 연산 : 2개의 원소가 포함된 집합을 하나의 집합으로 합치는 연산
• find(찾기) 연산 : 특정한 원소가 속한 집합이 어떤 집합인지 알려주는 연산
Union-Find 알고리즘
1. union(합집합) 연산을 확인하여, 서로 연결된 두 노드 A, B를 확인한다.
- A와 B의 루트 노드 A', B'를 각각 찾는다.
- A'를 B'의 부모 노드로 설정한다. (B'가 A'를 가리키도록 한다.)
2. 모든 union(합집합) 연산을 처리할 때까지 1번 과정을 반복한다.
* 일반적으로 더 번호가 작은 원소가 부모 노드(작은 원소를 가르킴)가 되도록 구현하는 경우가 많다.
* 부모 테이블을 통해 수행한다.
• Union-Find 알고리즘 소스코드
# 특정 원소가 속한 집합을 찾기 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 # 노드의 개수와 간선(union 연산)의 개수 입력받기 v, e = map(int, input().split()) parent = [0] * (v + 1) # 부모테이블 초기화 # 부모 테이블상에서, 부모를 자기 자신으로 초기화 for i in range(1, v + 1): parent[i] = i # union 연산을 각각 수행 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=' ')
• Union-Find 알고리즘의 시간 복잡도
노드의 개수 V, 최대 V - 1개의 union 연산과 M개의 find 연산이 가능할 때
O(V + M(1 + log2-M/VV)
Union-Find를 활용한 사이클 판별
서로소 집합은 그래프 내에서의 사이클을 판별할 때 사용할 수 있다.
union연산은 그래프에서의 간선으로 표현될 수 있다. 따라서 간선을 하나씩 확인하면서 두 노드가 포함되어있는 집합을 합치는 과정을 반복하면 사이클을 판별할 수 있다.
1. 각 간선을 확인하며 두 노드의 루트 노드를 확인한다.
- 루트 노드가 서로 다르다면 두 노드에 대하여 union 연산을 수행한다.
- 루트 노드가 서로 같다면 사이클이 발생한 것이다.
2. 그래프에 포함되어 있는 모든 간선에 대하여 1번 과정을 반복한다.
• 서로소 집합을 활용한 사이클 판별 소스코드
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 # 사이클이 발생하지 않았다면 합집합(union) 수행 else: union_parent(parent, a, b) if cycle: print("사이클이 발생했습니다.") else: print("사이클이 발생하지 않았습니다.")
* 이것이 코딩테스트다 with 파이썬 - 나동빈
'Algorithms in Python > notes' 카테고리의 다른 글
위상 정렬 (0) 2021.02.07 크루스칼 알고리즘 (0) 2021.02.07 DFS / BFS (0) 2021.01.29 이진 탐색, bisect 라이브러리 (0) 2021.01.21 파이썬의 정렬 라이브러리 (0) 2021.01.20