[java] 프로그래머스 - 섬 연결하기

1 분 소요

업데이트:

문제

프로그래머스-섬 연결하기
n개의 섬 사이에 다리를 건설하는 비용이 주어질 때 최소의 비용으로 모든 섬을 연결하는 가격을 구하는 문제
모든 섬 사이의 다리 건설비용이 주어지는 것은 아님(이 경우, 두 섬을 잇는 다리는 없음)
연결할 수 없는 섬은 주어지지 않음
두 섬을 연결하는 다리에는 방향성이 존재하지 않음

  • 예시
    img
    그림과 같이 섬과 다리건설 비용이 주어지는 경우, 초록색으로 연결하는 것이 가장 적은비용으로 모든 섬을 잇는 방법

풀이

크루스칼 알고리즘으로 풀었다
1) 다리의 연결 정보와 비용을 객체로 저장 후 정렬
우선 비용이 최소여야 하므로 다리의 연결정보와 비용을 객체로 만들어서 우선순위 큐에 저장했다.

2) union-find를 적용하기 위해 준비
union-find에서 필요한 부모 정보를 저장하기 위한 배열(chk)을 만들고 인덱스를 저장한다.

3) 최소 비용 순으로 다리 정보를 뽑으면서 연결된 두 섬이 연결되었는지 확인한다
두 섬이 연결되어있으면 건너뛰고, 연결되어있지 않으면 연결해준다
연결 시 비용을 추가해준다

소스코드

import java.util.PriorityQueue;

class Solution {
	static int chk[];

	public int solution(int n, int[][] c) {
		int answer = 0;
		// 1) 객체 생성 후 pq에 저장  
		PriorityQueue<Road> pq = new PriorityQueue<>();
		for (int i = 0; i < c.length; i++) {
			int ia = c[i][0];
			int ib = c[i][1];
			pq.add(new Road(ia, ib, c[i][2]));

		}
		// 2) chk배열 선언 후 i번째에는 i를 넣어줌(초기화)
		chk = new int[n];
		for (int i = 0; i < chk.length; i++) {
			chk[i] = i;
		}
		while (!pq.isEmpty()) {
			Road curr = pq.poll();
			// 3) 두 섬이 연결되어있지 않으면 두 섬을 이어줌, 비용 추가
			if (find(curr.x) != find(curr.y)) {
				union(curr.x, curr.y);
				answer += curr.cost;
			}
		}
		return answer;
	}

	private void union(int x, int y) {
		int p = find(x);
		int q = find(y);
		chk[p] = q;

	}

	private int find(int x) {
		if (chk[x] == x)
			return x;
		return find(chk[x]);
	}

}

class Road implements Comparable<Road> {
	int x;
	int y;
	int cost;

	public Road(int x, int y, int cost) {
		super();
		this.x = x;
		this.y = y;
		this.cost = cost;
	}

	@Override
	public int compareTo(Road r) {
		// TODO Auto-generated method stub
		return this.cost - r.cost;
	}
}

댓글남기기