Algorithm
Union-Find, Kruskal 정리
이충무
2022. 9. 21. 00:35
union - find
장점 : 만약 여러 개의 노드 무리들이 있다고 가정했을 때, 2개의 노드를 선택했을 때 그 노드들이 연결이 되어있는지 찾기가 용이하다.
예시 문제 - 프로그래머스 호텔 방배정
https://school.programmers.co.kr/learn/courses/30/lessons/64063
최소 스패닝 트리(MST)는, 주어진 그래프의 모든 정점들을 연결하는 부분 그래프 중에서 그 가중치의 합이 최소인 트리를 말한다.
입력으로 주어지는 그래프는 하나의 연결 그래프임이 보장된다.
이때 프림과 크루스칼 적용 → 주목적이 최소 스패닝 트리를 만드는 것
Kruskal → 시간복잡도O(ElogE)
import java.io.*;
import java.util.*;
class Edge implements Comparable<Edge>{
int from;
int to;
int cost;
public Edge(int from, int to, int cost) {
super();
this.from = from;
this.to = to;
this.cost = cost;
}
@Override
public int compareTo(Edge o) {
return (this.cost - o.cost);
}
}
public class Solution {
static int v;
static int e;
static int[] parents;
static ArrayList<Edge> edgeList;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
st= new StringTokenizer(br.readLine());
v= Integer.parseInt(st.nextToken());
e= Integer.parseInt(st.nextToken());
edgeList= new ArrayList<>();
make();
for (int i = 0; i < e; i++) {
st = new StringTokenizer(br.readLine(), " ");
int from = Integer.parseInt(st.nextToken());
int to = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
edgeList.add(new Edge(from, to, cost));
}
Collections.sort(edgeList);
long sumCost=0;
int cnt=0;
for (int i = 0, size = edgeList.size(); i < size; i++) {
Edge now = edgeList.get(i);
if(union(now.to, now.from)) {
sumCost += (long)now.cost;
cnt++;
}
}
//이때 cnt의 값이 무조건 정점개수 - 1 이어야한다.
System.out.println(sumCost);
}
static void make() {
parents = new int[v+1];
for (int i = 1; i <= v; i++) {
parents[i] = i;
}
}
static int find(int a) {
if (parents[a] == a)
return a;
return parents[a] = find(parents[a]);
}
static boolean union(int a, int b) {
int aRoot = find(a);
int bRoot = find(b);
if (aRoot == bRoot)
return false;
if(aRoot!=bRoot){
if(aRoot<bRoot) parents[bRoot]=aRoot;
else parents[aRoot] = bRoot;
}
return true;
}
}