
본 글에서는
MST가 무엇인지 알아봅니다.
MST를 구하는 알고리즘인 크루스칼 알고리즘에 대해서 알아봅니다.
최소 신장 트리(MST) ⊂ 신장 트리 ⊂ 부분 그래프









💡 그래프 표현 방식
1. 인접 리스트(adjacent list) : 각 정점에 연결된 정점을 리스트로 저장하는 방식
2. 인접 행렬(adjacent metrix) : 노드간의 연결 관계를 2차원 행렬로 나타내는 방식
3. 간선 리스트(edge list) : 그래프의 모든 간선을 [시작 노드, 종료 노드, 가중치] 형태로 리스트에 저장하는 방식
💡 union find란?
https://velog.io/@signkite/union-find
import java.util.*;
class Edge {
int v1;
int v2;
int weight;
Edge (int v1, int v2, int weight) {
this.v1 = v1;
this.v2 = v2;
this.weight = weight;
}
}
public class Main {
static int[] parents; // union find 에 사용
static String graph = "1 2 7\n" + // 정점1 정점2 가중치
"1 3 6\n" +
"1 5 9\n" +
"2 4 4\n" +
"2 6 2\n" +
"3 4 1\n" +
"3 5 8\n" +
"3 6 3\n" +
"4 6 5\n" +
"5 6 10\n";
static List<Edge> MST = new ArrayList<>(); // 최종적으로 구할 MST의 간선 리스트 표현
public static void main(String[] args) {
/* 그래프 정보 입력받기 */
Scanner sc = new Scanner(graph);
List<Edge> edges = new ArrayList<>();
for (int i = 0; i < 10; ++i) {
int v1 = sc.nextInt();
int v2 = sc.nextInt();
int weight = sc.nextInt();
edges.add(new Edge(v1, v2, weight));
}
/* 간선 리스트를 간선의 가중치가 작은 순서대로 정렬 */
Collections.sort(edges, (e1, e2) -> {
return e1.weight - e2.weight;
});
/* union find 를 사용해 사이클을 확인하기 위해 정점 집합 초기화 */
parents = new int[7];
for (int i = 1; i <= 6; ++i) {
parents[i] = i;
}
/* 사이클이 발생하지 않도록 가중치가 작은 간선부터 하나씩 선택 */
int selected = 0;
for (Edge cur: edges) {
/* 현재 간선의 양 끝점이 이미 연결되어 같은 집합에 속해있다면
* 현재 간선을 추가했을 때 사이클이 발생하게 되므로 건너뛴다. */
if (find(cur.v1) == find(cur.v2))
continue;
union(cur.v1, cur.v2);
MST.add(cur);
selected++;
/* (정점 수 - 1)개의 간선을 선택했다면 종료 */
if (selected == 6 - 1)
break;
}
/* 모든 정점이 연결되어있지 않아 MST를 만들 수 없는 경우 */
if (selected < 6 - 1) {
System.out.println("MST를 만들 수 없습니다.");
return;
}
/* 완성된 MST 출력 */
System.out.println("--- MST 완성! ---");
int totalWeight = 0;
for (Edge e: MST) {
System.out.printf("v1: %d, v2: %d, weight: %d\n", e.v1, e.v2, e.weight);
totalWeight += e.weight;
}
System.out.println("총 가중치: " + totalWeight);
}
/* union find 를 위한 메서드 */
static int find(int x) {
if (parents[x] == x)
return x;
return parents[x] = find(parents[x]);
}
static void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY)
parents[rootX] = rootY;
}
}
를 간선의 개수, 를 정점의 개수라 했을 때,
백준 1922 네트워크 연결
https://www.acmicpc.net/problem/1922