220218 - 섬 연결하기

◾ 섬 연결하기 : 프로그래머스 LEVEL 3

문제

n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.

다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.


입력

  • 섬의 개수 n은 1 이상 100 이하입니다.
  • costs의 길이는 ((n-1) * n) / 2이하입니다.
  • 임의의 i에 대해, costs[i][0] 와 costs[i][1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i][2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.
  • 같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.
  • 모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.
    연결할 수 없는 섬은 주어지지 않습니다.

출력

  • 섬 연결 최소 비용

입출력 예

ncostsreturn
4[[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]]4

◾ 풀이

1. 해설

  • 크루스칼 알고리즘을 이용해 섬을 연결하는 최소 비용을 구한다.
  • 건설 시 비용이 적게 드는 간선부터 연결한다.
    • 단, 루프가 발생하는 경우 해당 간선은 사용하지 않는다.
    • 선택된 간선이 (섬의 개수 - 1)인 경우 모든 섬이 연결된다.

2. 프로그램

  1. 간선 건설 비용을 기준으로 정렬(내림차순)
  2. 최저 비용 간선부터 차례로 추가하며 확인
  3. 루프가 생기는 경우 추가하지 않음
  4. 간선 비용을 더하여 반환
# 코드
def find(p, u):
    if u != p[u]:
        p[u] = find(p, p[u])
    return p[u]

def union(p, u, v):
    root1 = find(p, u)
    root2 = find(p, v)
    p[root2] = root1

def solution(n, costs):
    answer = 0
    p = [i for i in range(n+1)]
    costs.sort(key=lambda x : x[2], reverse=True)

    edges_cnt = 0
    while True:
        if edges_cnt == n-1:
            break
        u, v, cost = costs.pop()
        if u > v :
            u, v = v, u
        if find(p, u) != find(p, v):
            union(p, u, v)
            answer += cost
            edges_cnt += 1

    return answer

좋은 웹페이지 즐겨찾기