[알고리즘]Union - Find 알고리즘
Union-Find 알고리즘
union-find(합집합 찾기) 알고리즘은 disjoint set(서로소 집합)으로 불리기도 한다.
개념
- union-find는 서로 중복되지 않은 부분집합들로 나눠진 원소들에 대한 정보를 저장하고 조작하는 자료구조이다.
- 여러 개의 노드가 존재할 때 두개의 노드를 선택해서 이 노드가 서로 같은 그래프에 속하는지 판별하는 알고리즘이다.
- Kruskal 알고리즘에 활용되기 때문에 정확하게 이해해야하는 개념이다.
union-find(합집합 찾기) 알고리즘은 disjoint set(서로소 집합)으로 불리기도 한다.
Union
2개의 원소로 이루어진 집합을 하나의 집합으로 합치는 연산
Find
두개의 원소가 같은 그래프에 속하는지 판별하는 연산
구현
1. 초기화
각 노드의 부모노드를 노드 번호로 초기화
parent = []
for i in range(n+1):
parent.append(i)
2. 부모노드 찾기
재귀적으로 부모노드를 찾는다. => 부모노드와 현재 자기 지신의 노드를 반환하면 그 노드가 부모노드라는 뜻이므로 그대로 반환하고, 그렇지 않으면 재귀적으로 해당 요소의 값을 이용해 부모노드의 값을 찾는다.
def get_find(parent, x):
if parent[x] != x:
return get_find(parent, parent[x])
return x
3. union 연산
부모를 합칠때는 일반적으로 더 작은 값쪽으로 합친다.
def union_parent(parent,a,b):
a = get_find(parent,a)
b = get_find(parent,b)
if a < b :
parent[b] = a
else :
parent[a] = b
4. find 연산
두개의 노드가 같은 그래프에 속하는지 판별
def find_parent(parent,a,b):
a = get_find(parent,a)
b = get_find(parent,b)
if a == b:
return 1
else:
return 0
개선된 find 연산
위의 그림에서 보면 5번째 노드의 부모도느를 찾기 위해서 5 -> 4 -> 1의 과정을 거치게된다. 만약 굉장히 긴 트리구조에서 leaf 노드의 부모노드를 찾는다면 굉장히 비효율적일 것이다.
위와 같이 바꾼다면 더 빠르게 루트노드를 파악할 수 있다.
def get_find(parent, x):
if parent[x] != x:
return get_find(parent, parent[x])
return parent[x]
사이클 판별법
union find 알고리즘을 활용해서 그래프 내의 사이클을 판별할 수 있다.
- 두 노드의 루트 노드를 확인한다.
1-1 루트노드가 다르면 => Union 연산
1-2 루트노드가 같으면 => cycle 발생 - 모든 간선에 대해 1을 반복
for i in range(e):
a, b = map(int, input().split())
if find_parent(parent, a, b):
cycle = True
break
else:
union_parent(parent, a, b)
reference
Author And Source
이 문제에 관하여([알고리즘]Union - Find 알고리즘), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yujin1760/알고리즘Union-Find-알고리즘저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)