[알고리즘 고득점 kit][Level 3] 섬 연결하기

2025. 2. 25. 15:38·PROGRAMMERS

문제 설명

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

입출력 예 설명

costs를 그림으로 표현하면 다음과 같으며, 이때 초록색 경로로 연결하는 것이 가장 적은 비용으로 모두를 통행할 수 있도록 만드는 방법입니다.

 

 

Union-Find 알고리즘

- 유니온 파인드 알고리즘이란, 어떤 두 노드가 연결되어 있는지를 판별하는 알고리즘이다.

- 서로소 집합, 상호 배타적 집합이라고도 한다.

- 노드를 합치는 union 연산, 노드의 루트 노드를 찾는 find 연산으로 이루어 진다.

 

parent 노드를 저장하는 배열이 아래와 같다.

1 2 3 4 5 6
1 1 3 4 4 5

 

2번 노드의 루트노드를 찾는 과정

    1) 배열 2번에 있는 값을 확인한다. -> 1번

    2) 배열 1번에 있는 값을 확인한다. -> 1번

    3) 배열의 인덱스 값과 일치하므로, 1번 노드가 2번노드가 속해 있는 트리의 루트노드이다.

 

6번 노드의 루트노드를 찾는 과정

    1) 배열 6번에 있는 값을 확인한다. -> 5번

    2) 배열 5번에 있는 값을 확인한다. -> 4번

    3) 배열 4번에 있는 값을 확인한다. -> 4번

    4) 배열의 인덱스 값과 일치하므로, 4번 노드가 6번노드가 속해 있는 트리의 루트노드이다.

 

만약, 4번 노드와 5번 노드가 연결되어 있는가?를 확인하려면, 루트노드가 동일한지를 확인하면 된다. 이러한 과정은 재귀함수로 구할 수 있고, 유니온파인드의 find 연산이라고 한다. 아래는 예시 코드이다.

def isFind(k, parent):
	if parent[k] == k: # 배열의 인덱스와 값이 동일하면 k는 루트 노드
    	return k
    else: # 동일하지 않으면 재귀 처리
    	return isFind(parent[k], parent)

 

그렇다면, union 연산은 어떻게 하는걸까?

위 배열에서 1번 노드와 5번 노드를 연결하고 싶다고 하자. 두 노드는 루트 노드가 다르기 때문에, 연결되어 있지 않다.

따라서, 5번의 루트노드인 4번을 1번과 연결해주면 된다. 아래는 예시 코드이다.

parent[isFind(v2, parent)] = v1

 

 

위 알고리즘 개념을 바탕으로, 섬 연결하기를 풀 수 있다.

def isFind(k, parent):
    if parent[k] == k: # 배열 인덱스와 같다면, 루트 노드임
        return k
    else:
        return isFind(parent[k], parent) # 재귀
    
def solution(n, costs):
    answer = 0
    parent = [i for i in range(n)]
    costs.sort(key = lambda x: x[2])
    link = 0
    for v1, v2, w in costs:
        if isFind(v1, parent) != isFind(v2, parent):
            parent[isFind(v2, parent)] = v1
            answer += w
            link += 1
        if link == n-1:
            break
                             
    return answer

 

'PROGRAMMERS' 카테고리의 다른 글

[SQL 고득점 Kit][GROUP BY] 자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기  (1) 2025.02.12
[SQL 고득점 Kit][JOIN][Level 5] 상품을 구매한 회원 비율 구하기  (0) 2025.02.09
[SQL 고득점 Kit][JOIN] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기  (1) 2025.02.05
[SQL 고득점 Kit][JOIN] 없어진 기록 찾기  (0) 2025.02.02
[SQL 고득점 Kit][IS NULL][Level 3] 업그레이드 할 수 없는 아이템 구하기  (1) 2025.01.27
'PROGRAMMERS' 카테고리의 다른 글
  • [SQL 고득점 Kit][GROUP BY] 자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기
  • [SQL 고득점 Kit][JOIN][Level 5] 상품을 구매한 회원 비율 구하기
  • [SQL 고득점 Kit][JOIN] 특정 기간동안 대여 가능한 자동차들의 대여비용 구하기
  • [SQL 고득점 Kit][JOIN] 없어진 기록 찾기
콘순이
콘순이
개발 보안 관련 스터디 기록장
  • 콘순이
    SECURITY DEVELOPER
    콘순이
  • 글쓰기 관리
  • 전체
    오늘
    어제
    • 분류 전체보기 (71) N
      • BAEKJOON (45)
      • ALGORITHM (4)
      • QUALIFICATIONS (0)
      • PYTHON (1)
      • PROGRAMMERS (6)
      • DEVELOP (12) N
        • SPRING (4)
        • ERROR (0)
        • CONCEPT (5)
        • AWS (3) N
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    비트 조작
    문자열
    solid
    비트 마스킹
    Python
    알고리즘
  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.3
콘순이
[알고리즘 고득점 kit][Level 3] 섬 연결하기
상단으로

티스토리툴바