최소 연결문제구만 (최소신장트리)
최소신장트리 만들기 = 크루스칼
- 크루스칼 알고리즘
- 시간복잡도 : 간선갯수 E일때
- 아이디어 : 각 정점 간 간선의 가중치를 작은 순서대로 선택해 나가는데, union-find 연산으로 싸이클이 발생하는지 여부를 판단하면서 선택하는 것
크루스칼 자체를 구현하기보다,
크루스칼을 구현하는데 필요한 edge의 후보가 여러가지이고, 그 후보중에서 진짜 edge를 제한안에 구하는 것이 중요한 문제구만
# 특정 원소가 속한 집합을 찾기
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
n = int(input()) # 노드의 갯수 입력받기
parent = [0] * (n+1) # 부모 테이블 초기화
edges = [] # 모든 간선을 담을 리스트
result = 0 # 최종 비용을 담을 변수
# 부모 테이블상에서, 부모를 자기 자신으로 초기화
for i in range(1, n+1) :
parent[i] = i
x = []
y = []
z = []
# 모든 노드에 대한 좌표 값 입력받기
for i in range(1, n+1) :
data = list(map(int, input().split()))
x.append((data[0], i))
y.append((data[1], i))
z.append((data[2], i))
x.sort()
y.sort()
z.sort()
# 인접한 노드들로부터 간선 정보를 추출하여 처리
for i in range(n-1) :
# 비용순으로 정렬하기 위해서 튜플의 첫번째 원소를 비용으로 ㅓㅅㄹ정
edges.append((x[i+1][0] - x[i][0], x[i][1], x[i+1][1]))
edges.append((y[i+1][0] - y[i][0], y[i][1], y[i+1][1]))
edges.append((z[i+1][0] - z[i][0], z[i][1], z[i+1][1]))
# 간선을 비용순으로 정렬
edges.sort()
# 간선을 하나씩 확인하여
for edge in edges :
cost, a, b = edge
# 사이클이 발생하지 않는 경우에만 집합에 포함
if find_parent(parent, a) != find_parent(parent, b) :
union_parent(parent, a, b)
result += cost
print(result)