본문 바로가기

Problem Solving/Baekjoon Online Judge

[BOJ/백준] 4386번 별자리 만들기 | 최소 신장 트리 | 파이썬

문제 설명

 

문제 풀이

모든 별은 서로 직/간접적으로 이어져 있어야 하고, 별자리를 만드는 최소 비용을 구해야 한다고 해서 그래프 문제, 그중 최소 신장 트리 알고리즘을 사용하는 문제라고 생각했다.

* 신장 트리(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 함수를 호출하며 최소 비용을 계산했다.

 

유니온 파인드에 대한 내용은 여기서 확인😃

 


 

 

4386번: 별자리 만들기

도현이는 우주의 신이다. 이제 도현이는 아무렇게나 널브러져 있는 n개의 별들을 이어서 별자리를 하나 만들 것이다. 별자리의 조건은 다음과 같다. 별자리를 이루는 선은 서로 다른 두 별을 일

www.acmicpc.net

 

이것이 취업을 위한 코딩 테스트다 with 파이썬 - 교보문고

취업과 이직을 결정하는 알고리즘 인터뷰 완벽 가이드 | 이런 독자에게 권합니다.■ IT 직군의 취업 준비생 / 예비 개발자■ 이직을 준비하는 개발자■ 알고리즘 대회를 준비하는 학생[특징]코딩

www.kyobobook.co.kr