최소 신장 트리 (MST, Minimum Spanning Tree)
Spanning Tree
- 그래프 내의 모든 정점을 포함하는 트리
- 그래프의 최소 연결 부분 그래프
- 모든 정점들이 연결되어 있어야 하고, 사이클을 포함해서는 안됨
- 그래프에 있는 n개의 정점을 n-1 개의 간선으로 연결
MST의 특징
- 간선의 가중치의 합이 최소
- n개의 정점을 가지고 그래프에 대해 n-1 개의 간선만을 사용
- 사이클을 포함해서는 안됨
문제
https://www.acmicpc.net/problem/10021
풀이
처음에는 DFS + 백트래킹으로 풀었다가 시간 초과
이 문제는 MST 알고리즘으로 풀어야한다
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
class Main {
static String[] input;
static StringBuilder sb = new StringBuilder();
static int N, C;
static int[] parent;
// 유니온 파인드
// 부모(root) 노드를 찾는 과정
static int find(int n) {
if (n == parent[n])
return n;
return parent[n] = find(parent[n]);
}
// 연결된 두 노드의 부모 노드를 찾고, 하나의 부모 노드로 동기화 시켜준다
static void union(int x, int y) {
x = find(x);
y = find(y);
// 다른 부모 노드 값이 나온다면, 인덱스 값이 더 작은 노드를 부모 노드로 정한다
if (x < y)
parent[y] = x;
else
parent[x] = y;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
input = br.readLine().split(" ");
N = Integer.parseInt(input[0]);
C = Integer.parseInt(input[1]);
Node[] node = new Node[N];
for (int i = 0; i < N; i++) {
input = br.readLine().split(" ");
// Node( x좌표, y좌표, 0) 으로 생각
node[i] = new Node(Integer.parseInt(input[0]), Integer.parseInt(input[1]), 0);
}
// 비용(cost)가 적은
PriorityQueue<Node> pq = new PriorityQueue<>((n1, n2) -> n1.cost - n2.cost);
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; j++) {
int cost = (int) Math.pow(node[i].x - node[j].x, 2) + (int) Math.pow(node[i].y - node[j].y, 2);
// 노드간 비용이 최소 비용을 넘어야만 (관계를 사용할 수 있기 때문에) 우선순위 큐에 넣는다.
if (C <= cost) {
// Node ( i번호 노드, j번호 노드, 비용)
pq.add(new Node(i, j, cost));
}
}
}
// 노드들의 부모 노드를 자기 자신으로 초기화
parent = new int[N];
for (int i = 0; i < N; i++)
parent[i] = i;
int result = 0;
int count = 0; // 모든 정점을 방문했는지 확인하기 위한 변수
// 우선순위 큐는 가장 최소 비용을 가진 노드 관계를 우선적으로 뽑는다
while (!pq.isEmpty()) {
Node n = pq.poll(); // x번 노드, y번 노드, 비용
if (find(n.x) == find(n.y)) // 노드 관계가 확인된 것이라면 continue
continue;
union(n.x, n.y); // union 합친다
count += 1; // 1개의 노드 관계를 카운트
result += n.cost;
}
// 노드 개수가 N개라면 관계는 N-1개이다. 위에서 중복되지않고 모든 노드를 차례로 관계를 확인했다면 count == N-1
System.out.println(count < N - 1 ? -1 : result);
br.close();
}
}
class Node {
int x, y, cost;
Node(int x, int y, int cost) {
this.x = x;
this.y = y;
this.cost = cost;
}
}
참고 사이트
[알고리즘] 최소 신장 트리(MST, Minimum Spanning Tree)란 - Heee's Development Blog
Step by step goes a long way.
gmlwjd9405.github.io
'알고리즘 ' 카테고리의 다른 글
[프로그래머스] 억억단을 외우자 (0) | 2022.11.26 |
---|---|
[알고리즘] Union-Find (유니온 파인드) (0) | 2022.08.21 |
[JAVA] 단체사진 찍기 (2017 카카오코드 본선) (0) | 2022.06.18 |
SCC - Tarjan (타잔 알고리즘) (0) | 2019.07.11 |
[알고스팟] WILDCARD - JAVA (0) | 2019.06.06 |