👀 문제
https://www.acmicpc.net/problem/1197
👊 도전
1. 설계
- 크루스칼 알고리즘을 이용한다(프림도 가능).
- 가중치 기준 우선순위 큐에서 노드를 뽑는다.
- Union-Find를 이용해 start와 end가 연결되어있는지 확인한다(공통 부모 체크).
- 아닐 경우 둘을 연결하고 가중치 합을 누적한다.
2. 구현 (성공 코드)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.util.*;
import java.io.*;
/**
* @author HEESOO
*
*/
class Main {
static PriorityQueue<Node> pq;
static int[] parent;
public static void main(String[] args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st=new StringTokenizer(br.readLine());
pq=new PriorityQueue<>();
int v=Integer.parseInt(st.nextToken());
int e=Integer.parseInt(st.nextToken());
parent=new int[v+1];
for(int i=1;i<=v;i++) parent[i]=i; // 부모는 나 자신으로 초기화
for(int i=0;i<e;i++) {
st=new StringTokenizer(br.readLine());
int a=Integer.parseInt(st.nextToken());
int b=Integer.parseInt(st.nextToken());
int c=Integer.parseInt(st.nextToken());
pq.offer(new Node(a, b, c)); // 큐에 다 넣기
}
System.out.println(solve());
}
public static int solve() {
int sum=0; // 가중치 누적 합 계산
while(!pq.isEmpty()) {
Node node=pq.poll();
// start, end의 부모 찾기
int parentS=find(node.start);
int parentE=find(node.end);
// 부모가 다르다면(연결되어있지 않다면)
if(parentS!=parentE) {
union(parentS, parentE); // 둘을 연결
sum+=node.weight; // 가중치 계산
}
}
return sum;
}
public static int find(int x) {
if(parent[x]==x) return x;
else return parent[x]=find(parent[x]);
}
public static void union(int a, int b) {
parent[a]=b;
}
}
class Node implements Comparable<Node>{
int start;
int end;
int weight;
public Node(int s, int e, int w) {
this.start=s;
this.end=e;
this.weight=w;
}
@Override
public int compareTo(Node n) { // 가중치 기준 오름차순 정렬
return this.weight-n.weight;
}
}
3. 결과
🤟 성공 🤟
4. 설명
- 크루스칼 알고리즘을 이용한다
- MST는 크루스칼 또는 프림으로 해결할 수 있다.
- E 개수가 적으면 크루스칼, V 개수가 적은 것은 프림을 쓰는게 좋다.
- 크루스칼은 V가 작은 것부터 체크한다. 이를 위해 우선순위 큐를 이용한다. 가중치가 작은 것부터 확인하기 때문에 최소 weight로 노드들을 연결할 수 있다.
- 사이클을 방지하기 위해 두 노드(start, end)의 최상위 부모를 체크하고, 부모가 다르면 두 노드가 연결되어 있지 않은 것이므로 연결한다.
👏 해결 완료!
참고
- [Java][자바][백준][1197번] 최소 스패닝 트리 - 크루스칼 알고리즘 https://ju-nam2.tistory.com/112