문제 설명
문제 풀이
모든 별은 서로 직/간접적으로 이어져 있어야 하고, 별자리를 만드는 최소 비용을 구해야 한다고 해서 그래프 문제, 그중 최소 신장 트리 알고리즘을 사용하는 문제라고 생각했다.
* 신장 트리(Spanning Tree): 하나의 그래프에서 모든 노드를 포함하면서 사이클이 존재하지 않는 부분 그래프. 최소 신장 트리는 신장 트리 중에서도 최소 비용으로 만들 수 있는 신장 트리를 찾는 알고리즘이다.
최근에 이코테에서 크루스칼 알고리즘에 대해 공부했기 때문에 이를 적용해보기로 했다!
크루스칼 알고리즘(Kruskal Algorithm)의 과정은 다음과 같다.
1) 간선 데이터 오름차순으로 정렬하기
2) 간선을 확인하며
2-1) 사이클이 만들어지면 pass
2-2) 사이클이 만들어지지 않으면 최소 신장 트리에 포함
3) 모든 간선에 대해 반복
❗ 이코테 예시에서는 모든 간선에 대한 정보가 주어진 것과 달리, 이 문제에서는 모든 별의 좌표가 주어져서 간선의 정보를 직접 계산해야 한다는 게 차이점이었다.
전체 코드
import math
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 = []
stars = []
# 최소 비용을 담을 변수
result = 0
for i in range(1, n + 1):
parent[i] = i
for _ in range(n):
a, b = map(float, input().split())
stars.append((a, b))
# 모든 별 사이의 거리 계산
for i in range(n - 1):
for j in range(i + 1, n):
edges.append((math.sqrt((stars[i][0] - stars[j][0]) ** 2 + (stars[i][1] - stars[j][1]) ** 2), i, j))
# 간선을 비용 순으로 정렬
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)
간선을 하나씩 확인하는 과정에서는 유니온 파인드(Union-Find)를 사용했다. 두 노드의 부모가 같은 지 확인하고, 다른 경우 union 함수를 호출하며 최소 비용을 계산했다.
유니온 파인드에 대한 내용은 여기서 확인😃
'Problem Solving > Baekjoon Online Judge' 카테고리의 다른 글
[BOJ/백준] 5014번 스타트링크 | BFS | 파이썬 (0) | 2022.05.04 |
---|---|
[BOJ/백준] 10799번 쇠막대기 | 스택 | 파이썬 (0) | 2021.09.29 |
[BOJ/백준] 2630번 색종이 만들기 | 분할정복 | 파이썬 (0) | 2021.09.28 |
[BOJ/백준] 5430번 AC | 덱 | 파이썬 (2) | 2021.09.01 |
[BOJ/백준] 1874번 스택 수열 | 파이썬 (2) | 2021.08.26 |