문제 풀이/Python

[programmers] 섬 연결하기

일 월 2023. 8. 25. 23:40

https://school.programmers.co.kr/learn/courses/30/lessons/42861

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제 설명

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의 비용이 주어지지 않습니다.
  • 모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.
  • 연결할 수 없는 섬은 주어지지 않습니다.

풀이

# 프림
def solution(n, costs):
    from heapq import heappush, heappop
    from collections import defaultdict
    min_cost = cnt = 0
    visited = set()
    heap = []
    link_info = defaultdict(list)
    for num1, num2, cost in costs:
        link_info[num1].append((cost, num2))
        link_info[num2].append((cost, num1))
    for i in range(n+1):
        if link_info.get(i):
            visited.add(i)
            for element in link_info[i]:
                heappush(heap, element)
            break

    while cnt < n-1:
        cost, num = heappop(heap)
        if num not in visited:
            visited.add(num)
            min_cost += cost
            cnt += 1
            for element in link_info[num]:
                if element[1] not in visited:
                    heappush(heap, element)

        if not heap:
            break

    return min_cost

'''
정확성  테스트
테스트 1 〉	통과 (0.01ms, 10.2MB)
테스트 2 〉	통과 (0.02ms, 10.1MB)
테스트 3 〉	통과 (0.03ms, 10.2MB)
테스트 4 〉	통과 (0.07ms, 10.1MB)
테스트 5 〉	통과 (0.03ms, 10MB)
테스트 6 〉	통과 (0.05ms, 10.3MB)
테스트 7 〉	통과 (0.06ms, 10.1MB)
테스트 8 〉	통과 (0.03ms, 10.2MB)
'''
# 크루스칼
def solution(n, costs):
    min_cost = cnt = i = 0
    root_of = list(range(n))
    rank = [1] * n
    costs.sort(key=lambda cost: cost[2])
    def find_root(num):
        if root_of[num] == num:
            return num
        result = find_root(root_of[num])
        root_of[num] = result
        return result

    def has_same_root(num1, num2):
        root1, root2 = find_root(num1), find_root(num2)
        if root1 == root2:
            return True
        if rank[root1] <= rank[root2]:
            rank[root2] += rank[root1]
            root_of[root1] = root2
        else:
            rank[root1] += rank[root2]
            root_of[root2] = root1
        return False

    while cnt < n-1:
        num1, num2, cost = costs[i]
        if not has_same_root(num1, num2):
            min_cost += cost
            cnt += 1
        i += 1

    return min_cost

'''
정확성  테스트
테스트 1 〉	통과 (0.01ms, 10.3MB)
테스트 2 〉	통과 (0.02ms, 10.2MB)
테스트 3 〉	통과 (0.03ms, 10.2MB)
테스트 4 〉	통과 (0.03ms, 10.2MB)
테스트 5 〉	통과 (0.02ms, 10.3MB)
테스트 6 〉	통과 (0.03ms, 10.2MB)
테스트 7 〉	통과 (0.05ms, 10.2MB)
테스트 8 〉	통과 (0.02ms, 10.1MB)
'''