Problem Solving/Online Judge
[프로그래머스] 섬 연결하기
se0m
2024. 9. 5. 10:28
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
💬 문제 설명
연결되어 있는 두 정점 정보와 가중치 정보가 주어졌을 때 최소 비용(간선의 가중치의 합)으로 모든 섬을 연결하고 해당 최소 비용을 반환하라.
📌 주의 사항
- 모든 섬 연결 + 최소 비용 → 최소 신장 트리(MST) 구성
👌 문제 풀이
- 모든 섬을 최소 비용으로 연결해야 하므로 최소 신장 트리 알고리즘을 사용해야 한다.
- 간선 정보를 알려주고 있으므로 간선 배열로 만들어서 사용하자.
- 간선 배열이므로 크루스칼 알고리즘을 사용해야겠다!
- 간선 배열을 가중치로 오름차 순 정렬
- 모든 간선이 연결될 때까지 union-find 진행
- 두 간선을 연결했을 때 사이클이 발생하지 않으면 union하고 총 비용에 해당 간선의 가중치를 더해줌
💻 코드
import java.util.Arrays;
class Solution {
public int[] parents;
public int solution(int n, int[][] costs) {
// 1. 간선 배열 정의
Edge[] edges = new Edge[costs.length];
for (int i = 0; i < costs.length; i++) {
int u = costs[i][0];
int v = costs[i][1];
int w = costs[i][2];
edges[i] = new Edge(u, v, w);
}
// 2. union-find를 위한 부모 배열 정의
parents = new int[n];
for (int i = 0; i < n; i++) {
parents[i] = i;
}
// 3. 가중치로 오름차순 정렬
Arrays.sort(edges);
// 4. 크루스칼로 MST 구성
int result = 0; // 총 비용
int count = 0; // 연결 간선 수
for (Edge edge: edges) {
if (union(edge.u, edge.v)) { // 싸이클이 발생하지 않았으면 (같은 집합에 없다면)
result += edge.w;
if (++count == n - 1) { // 연결 간선 수가 (정점 수 - 1) 이면 다 연결한 것임
break;
}
}
}
return result;
}
int find(int u) {
if (parents[u] == u) {
return u;
}
return parents[u] = find(parents[u]);
}
boolean union(int u, int v) {
u = find(u);
v = find(v);
if (u == v) {
return false;
}
if (u < v) {
parents[v] = u;
} else {
parents[u] = v;
}
return true;
}
}
// 간선 정보를 담을 클래스
class Edge implements Comparable<Edge> {
int u, v, w;
Edge(int u, int v, int w) {
this.u = u;
this.v = v;
this.w = w;
}
// 가중치로 오름차순 정렬
@Override
public int compareTo(Edge e) {
return this.w - e.w;
}
}
🎓 배운 것
- 크루스칼 알고리즘 외워가는 중...