

"서로" "소"가 서 있네요
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
{1, 2, 3}과 {4, 5, 6}은 서로소 관계{1, 2}와 {2, 3, 4}는 서로소 관계가 아님 -> 공통 원소 2를 가짐

A와 B의 합집합 연산은, A가 속한 집합과 B가 속한 집합을 합침A의 루트 노드와, 노드 B의 루트 노드를 찾음




입력
N = 6 # 노드의 개수
parent = [i for i in range(N + 1)] # 부모 테이블
parent는 편의상 0~6번 인덱스를 갖는 길이 7의 리스트로 만들었으며, 0번 인덱스는 사용하지 않음찾기 연산
# 부모 테이블 parent를 이용해, x의 루트 노드 찾기
def find(parent, x):
# 루트를 찾을 때까지 (부모가 자기 자신일 때까지)
if parent[x] != x:
# 자신의 부모의 루트를 찾기
return find(parent, parent[x])
return x
x의 루트를 찾을 때까지, 즉 x의 부모가 자기 자신일 때까지 재귀 호출합집합 연산 수행
# 두 원소가 속한 집합 합치기
def union(parent, a, b):
# 두 원소의 루트 찾기
a = find(parent, a)
b = find(parent, b)
# 한쪽 루트를 다른쪽 루트의 부모로 설정
if a < b:
parent[b] = a
else:
parent[a] = b
find로 두 원소의 루트를 찾고, 더 큰 노드의 부모를 작은 노드로 지정연산 결과
union_list = [(1, 4), (2, 3), (2, 4), (5, 6)] # 실행할 합집합 연산 수행
- 루트 노드가 같으면, 사이클이 발생한 것- 모든 간선에 대해 위 과정을 반복
목록
for a, b in union_list:
union(parent, a, b)
for i in range(1, N + 1):
print(f"{i}번 노드: {find(parent, i)}번 노드가 루트인 집합에 속함")
print()
# 1번 노드: 1번 노드가 루트인 집합에 속함
# 2번 노드: 1번 노드가 루트인 집합에 속함
# 3번 노드: 1번 노드가 루트인 집합에 속함
# 4번 노드: 1번 노드가 루트인 집합에 속함
# 5번 노드: 5번 노드가 루트인 집합에 속함
# 6번 노드: 5번 노드가 루트인 집합에 속함

find 함수만 바꾸어 주면 됨def find(parent, x):
# 루트를 찾을 때까지 (부모가 자기 자신일 때까지)
if parent[x] != x:
# 자신의 부모의 루트를 찾고, 결과를 저장
parent[x] = find(parent, parent[x])
return parent[x]
find() 함수로 자신의 부모의 루트를 찾은 뒤, 이 값을 부모 테이블에 갱신find() 함수 실행 시 부모 테이블의 값이 루트 노드로 갱신됨
find, union 함수는 앞선 코드와 동일(노드 1, 노드 2) 꼴로 edges 리스트에 포함def find(parent, x):
if parent[x] != x:
parent[x] = find(parent, parent[x])
return parent[x]
def union(parent, a, b):
a = find(parent, a)
b = find(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
# N: 노드의 수, edges: 간선 리스트
def find_cycle(N, edges):
# 부모 테이블
parent = [i for i in range(N + 1)]
# 간선으로 이어진 두 노드 a, b
for a, b in edges:
# 동일 집합에 있으면 사이클 존재
if find(parent, a) == find(parent, b):
return True
# 다른 집합에 있으면 합집합 연산
union(parent, a, b)
return False
print(find_cycle(3, [(1, 2), (1, 3), (2, 3)])) # True
print(find_cycle(4, [(1, 2), (2, 3), (3, 4)])) # False
신장 트리의 간선 개수 = 노드 개수 - 1





2 + 3 + 4 + 5 + 7 = 21find, union 함수는 앞선 코드와 동일(가중치, 노드 1, 노드 2)만 edges 리스트에 포함list.sort()는 기본적으로 튜플의 첫 원소를 기준으로 정렬하므로, 가중치를 맨 앞에 둠def find(parent, x):
if parent[x] != x:
parent[x] = find(parent, parent[x])
return parent[x]
def union(parent, a, b):
a = find(parent, a)
b = find(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
N = 6
parent = [i for i in range(N + 1)] # 부모 테이블
# 간선 정보: (가중치, 노드1, 노드2)
edges = [(9, 1, 2), (7, 1, 4), (2, 2, 3), (8, 2, 4), (6, 3, 4), (4, 3, 5), (3, 3, 6), (5, 4, 5)]
edges.sort() # 기본적으로 튜플의 첫 순서 기준으로 정렬됨
# 최소신장트리의 가중치 합
answer = 0
for cost, a, b in edges:
# 사이클 발생 시 포함 X
if find(parent, a) == find(parent, b):
continue
else:
answer += cost # answer에 가중치를 더함
union(parent, a, b)
print(answer) # 21
(find) 연산에서 재귀가 많이 발생하게 되므로, sys.setrecursionlimit(10**6) 설정 잊지 않기import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**6)
def find(parent, x):
if parent[x] != x:
parent[x] = find(parent, parent[x])
return parent[x]
def union(parent, a, b):
a = find(parent, a)
b = find(parent, b)
if a < b:
parent[b] = a
else:
parent[a] = b
V, E = map(int, input().split())
parent = [i for i in range(V + 1)]
edges = []
# 가중치, 노드1, 노드2 순
for _ in range(E):
a, b, cost = map(int, input().split())
edges.append((cost, a, b))
edges.sort()
answer = 0
# 각 가중치에 대해..
for cost, a, b in edges:
if find(parent, a) == find(parent, b):
continue
else:
answer += cost
union(parent, a, b)
print(answer)
힘내세요...