https://www.acmicpc.net/problem/4386

 

4386번: 별자리 만들기

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

www.acmicpc.net


  • 노드들이 각자 최소한으로 연결되면서 최소한의 거리를 가져야 한다.
  • 모든 노드들에 대해 서로의 거리를 계산할 수 있기 때문에, 전체 그래프에서 가능한 에지와 거리를 우선순위 큐로 저장한다.
  • Min Heap 을 사용하여 가장 짧은 거리를 가지는 노드들을 순서대로 연결시켜준다.
  • 이 때 이번 에지를 추가함으로써 그래프에서 순환이 생길 경우엔 굳이 연결시킬 필요가 없기 때문에 제외한다.
  • 그래프의 순환은 유니온파인드로 두 노드를 탐색하여 검사해준다.
  • 찾아보니 이게 최소 스패닝 트리를 구하기 위한 크루스칼 알고리즘이라고 한다. 혼자 생각했다니 괜히 뿌듯하기도..

import heapq

def dist(X, Y):
    return ((X[0] - Y[0])**2 + (X[1] - Y[1])**2) ** 0.5

def find_(x):
    global parent
    if parent[x] == -1:
        return x
    parent[x] = find_(parent[x])    # path compression
    return parent[x]

def union_(x, y):                   # 유니온파인드
    global parent
    x = find_(x)
    y = find_(y)
    parent[x] = y

n = int(input())
stars = [tuple(map(float, input().split())) for i in range(n)]

distances = [(dist(stars[i], stars[j]), (i,j)) for i in range(n) for j in range(i+1, n)]
heapq.heapify(distances)                    # 가능한 에지들에 대하여 모두 거리를 기준으로 정렬(중복 제거)

answer = 0
parent = [-1] * n

while len(distances):                       # 에지들을 짧은 연결 순서대로 검사하면서 (크루스칼)
    d, (x, y) = heapq.heappop(distances)
    if find_(x) != find_(y):                # 순환 구조가 이루어지지 않는다면 (유니온파인드로 검사)
        union_(x, y)                        # 두 노드를 연결해줌
        answer += d

print(f"{answer:.2f}")

'PS > BOJ' 카테고리의 다른 글

[백준] 9252 : LCS 2  (0) 2021.06.13
[백준] 1647 : 도시 분할 계획  (0) 2021.06.12
[백준] 11054 : 가장 긴 바이토닉 부분 수열  (0) 2021.06.10
[백준] 15723 : n단 논법  (0) 2021.06.09
[백준] 3190 : 뱀  (0) 2021.06.08

+ Recent posts