서로소 집합 자료구조는 알고리즘이 아니라 자료구조로 분류된다. 서로소 집합 자료구조의 union과 find 연산이 사이클 판별 알고리즘에서 이용되기 때문에 사이클 판별을 하기 위해 서로소 집합 자료구조를 먼저 공부해야한다!
# 서로소 집합 자료구조 : 기본적인 구현 방법
# 연산 1 : 특정 원소가 속한 집합(루트 노드)를 찾아주는 연산 (find)
def find_parent(parent, x):
# 루트 노드를 찾을 때까지 재귀 호출
if parent[x] != x:
return find_parent(parent, parent[x])
return x
# 연산 2 : 두 원소가 속한 집합을 합치는 연산 (union)
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
# 입력
num_node, num_edge = map(int, input().split())
parent_table = [0] * (num_node + 1)
# 부모 테이블 초기화
for i in range(1, num_node + 1):
parent_table[i] = i;
# Union 연산을 입력받아 수행
for i in range(num_edge):
a, b = map(int, input().split())
union_parent(parent_table, a, b)
# 출력
print('각 원소가 속한 집합: ', end="")
for i in range(1, num_node + 1):
print(find_parent(parent_table, i), end=' ')
print()
print('부모 테이블: ', end="")
for i in range(1, num_node + 1):
print(parent_table[i], end=" ")
'''
입력
6 4
1 4
2 3
2 4
5 6
'''
'''
출력
각 원소가 속한 집합 : 1 1 1 1 5 5
부모 테이블 : 1 1 2 1 5 5
'''
find_parent
: basic
def find_parent(parent, x):
# x가 루트 노드가 아니라면
if parent[x] != x:
# x의 루트 노드를 찾아서 return
return find_parent(parent, parent[x])
# x가 루트 노드라면 바로 return
return x
find_parent
: with path compression
def find_parent(parent, x):
# x가 루트 노드가 아니라면
if parent[x] != x:
# x의 루트 노드를 찾아서 parent 값으로 저장해주고 return
parent[x] = find_parent(parent, parent[x])
# x가 루트 노드라면 바로 return
return parent[x]
find_parent
: with 긍정 조건문
def find_parent(parent, x):
if parent[x] == x:
return parent[x]
return parent[x] = find_parent(parent, parent[x])
# 서로소 집합 자료구조 : 기본적인 구현 방법
# 연산 1 : 특정 원소가 속한 집합(루트 노드)를 찾아주는 연산 (find)
def find_parent(parent, x):
if parent[x] != x:
parent[x] = find_parent(parent, parent[x])
return parent[x]
# 연산 2 : 두 원소가 속한 집합을 합치는 연산 (union)
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
# 입력
num_node, num_edge = map(int, input().split())
parent_table = [0] * (num_node + 1)
# 부모 테이블 초기화
for i in range(1, num_node + 1):
parent_table[i] = i;
# Union 연산을 입력받아 수행
for i in range(num_edge):
a, b = map(int, input().split())
union_parent(parent_table, a, b)
# 출력
print('각 원소가 속한 집합: ', end="")
for i in range(1, num_node + 1):
print(find_parent(parent_table, i), end=' ')
print()
print('부모 테이블: ', end="")
for i in range(1, num_node + 1):
print(parent_table[i], end=" ")
# 서로소 집합을 활용한 사이클 판별
# 연산 1 : 특정 원소가 속한 집합(루트 노드)를 찾아주는 연산 (find)
def find_parent(parent, x):
if parent[x] != x:
parent[x] = find_parent(parent, parent[x])
return parent[x]
# 연산 2 : 두 원소가 속한 집합을 합치는 연산 (union)
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
# 입력
num_node, num_edge = map(int, input().split())
parent_table = [0] * (num_node + 1)
# 부모 테이블 초기화
for i in range(1, num_node + 1):
parent_table[i] = i
# 사이클 판별
cycle = False # 사이클 발생 여부
for i in range(num_edge):
a, b = map(int, input().split())
# 사이클이 발생한 경우
if find_parent(parent_table, a) == find_parent(parent_table, b):
cycle = True
break
# 사이클이 발생하지 않은 경우
else:
union_parent(parent_table, a, b)
# 출력
if cycle:
print("사이클이 발생했습니다.")
else:
print("사이클이 발생하지 않았습니다.")