섬 연결하기 (level 3)

원용현·2022년 10월 5일
0

프로그래머스

목록 보기
27/49

링크

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

문제

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

문제 풀이


각 섬끼리 다리를 건설할 때 드는 비용이 주어진다면 위의 사진과 같이 다리를 건설하면 가장 최소 비용이 나온다.

이 문제는 크루스칼 알고리즘과 그리드 알고리즘, Union-Find 알고리즘을 이해해야 풀이가 가능하다.

각 알고리즘에 대해서 링크를 남기니 먼저 읽어보고 오면 문제 풀이가 가능할 것이다.

그리드 알고리즘
Union-Find 알고리즘
크루스칼 알고리즘

코드

function solution(n, costs) {
    let cost = 0
    let parent = new Array(n).fill(0)
    parent.map((el, idx) => parent[idx] = idx)
    costs.sort((a, b) => a[2] - b[2])
    
    costs.map((el) => {
        if(!findParent(parent, el[0], el[1])) {
            cost += el[2]
            union(parent, el[0], el[1])
        }
        console.log(el, parent, cost)
    })
    
    return cost
}

const union = (parent, x, y) => {
    const node1 = getParent(parent, x)
    const node2 = getParent(parent, y)
    
    if(node1 < node2) parent[node2] = node1
    else parent[node1] = node2
}

const findParent = (parent, x, y) => {
    const node1 = getParent(parent, x)
    const node2 = getParent(parent, y)
    
    if(node1 === node2) return true
    else return false
}

const getParent = (parent, x) => {
    if(parent[x] === x) return x
    return getParent(parent, parent[x])
}

코드 풀이

현재 노드가 가리키는 부모 노드가 무엇인지 저장할 배열을 먼저 만든다. 해당 배열은 자신의 인덱스 값을 요소로 가지도록 코드를 구성한다.

크루스칼 알고리즘을 적용하기 위해서 간선과 비용이 나와있는 배열을 비용값으로 오름차순 정렬을 진행한다.

배열의 요소들로 map 함수를 돌리는데 간선을 이루는 노드들의 부모노드가 같으면 해당 간선을 연결할 경우에 사이클이 발생해 최소 신장 트리(MST)를 만족하지 못하므로 부모노드가 같지 않을 경우에 간선을 연결한다.

해당 간선의 비용을 마지막에 반환해줄 변수에 저장하고 부모노드를 같게 만들어준다.

union 함수 : 두 노드의 부모노드를 같게 만들어주는 함수
findParent 함수 : 두 노드의 부모노드가 같은지 판별하는 함수
getParent 함수 : 노드의 부모노드 값을 반환하는 함수

0개의 댓글