티끌모아 로키산맥 🏔
search

로ᄏl
배움에 끝은 없다... 개발 또한 그러하다.
Today
Yesterday
신장 트리
신장트리는 모든 노드가 다 연결되어있지만, 일부 간선을 사용하지 않아도 괜찮다는 점에서 실제 문제 상황에서도 이런 아이디어가 효과적으로 사용될 수 있는 경우가 존재한다.
지금 예시의 테이블은 가독성을 위해 간선에 따라서 나열했지만, 실제 크루스칼 알고리즘은 비용을 오름차순으로 정렬
하는 작업이 우선적으로 수행되어야한다.
참고로 최종적으로 만들어지는 최소신장트리에 포함되어있는 간선의 갯수는 전체 노드의 개수 - 1
이다. 이는 기본적으로 트리
가 가지는 특징이고 사이클 또한 존재하지 않는다는
특징이 있다.
[Step 4] 아직 처리하지 않은 간선 중에서 가장 짧은 간선인 (6, 7)을 선택하여 처리한다.
이미 같은 집합에 속해있기 때문에 해당 간선은 무시한다.
[Step 5] 아직 처리하지 않은 간선 중에서 가장 짧은 간선인 (1, 2)을 선택하여 처리한다.
[Step 7] 아직 처리하지 않은 간선 중에서 가장 짧은 간선인 (2, 3)을 선택하여 처리한다.
이미 같은 집합에 속해있기 때문에 해당 간선은 무시한다.
[Step 8] 아직 처리하지 않은 간선 중에서 가장 짧은 간선인 (5, 6)을 선택하여 처리한다.
[Step 9] 아직 처리하지 않은 간선 중에서 가장 짧은 간선인 (1, 5)을 선택하여 처리한다.
이미 같은 집합에 속해있기 때문에 해당 간선은 무시한다.
[알고리즘 수행 결과]
public class Kruskal {
// 노드의 개수(V)와 간선(Union 연산)의 개수(E)
// 노드의 개수는 최대 100,000개라고 가정
private static int v, e;
private static int[] parent = new int[1000001]; // 부모 테이블 초기화하기
// 모든 간선을 담을 리스트와, 최종 비용을 담을 변수
private static List<Edge> edges = new ArrayList<>();
private static int result = 0;
// 특정 원소가 속한 집합을 찾기
private static int findParent(int x) {
// 루트 노드가 아니라면, 루트 노드를 찾을 때까지 재귀적으로 호출
if (x != parent[x]) {
parent[x] = findParent(parent[x]);
}
return parent[x];
}
// 두 원소가 속한 집합을 합치기
private static void unionParent(int a, int b) {
a = findParent(a);
b = findParent(b);
if (a < b) {
parent[b] = a;
return;
}
parent[a] = b;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
v = sc.nextInt();
e = sc.nextInt();
// 부모 테이블상에서, 부모를 자기 자신으로 초기화
for (int i = 1; i <= v; i++) {
parent[i] = i;
}
// 모든 간선에 대한 정보를 입력 받기
for (int i = 0; i < e; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
int cost = sc.nextInt();
edges.add(new Edge(cost, a, b));
}
// 간선을 비용순으로 정렬
Collections.sort(edges);
// 간선을 하나씩 확인하며
for (int i = 0; i < edges.size(); i++) {
int cost = edges.get(i).getDistance();
int a = edges.get(i).getNodeA();
int b = edges.get(i).getNodeB();
// 사이클이 발생하지 않는 경우에만 집합에 포함
if (findParent(a) == findParent(b)) {
continue;
}
unionParent(a, b);
result += cost;
}
System.out.println(result);
}
static class Edge implements Comparable<Edge> {
private int distance;
private int nodeA;
private int nodeB;
public Edge(int distance, int nodeA, int nodeB) {
this.distance = distance;
this.nodeA = nodeA;
this.nodeB = nodeB;
}
public int getDistance() {
return distance;
}
public int getNodeA() {
return nodeA;
}
public int getNodeB() {
return nodeB;
}
// 거리(비용)가 짧은 것이 높은 우선순위를 가지도록 설정
@Override
public int compareTo(Edge other) {
if (this.distance < other.distance) {
return -1;
}
return 1;
}
}
}
7. 최단 경로 알고리즘 - 다익스트라(Dijkstra) (1) | 2021.08.20 |
---|---|
8. 위상 정렬 (0) | 2021.08.18 |
Do it! 자료구조와 함께 배우는 알고리즘 입문 - 재귀 알고리즘 (0) | 2019.12.29 |
Do it! 자료구조와 함께 배우는 알고리즘 입문 - 검색 (0) | 2019.12.18 |
[알고리즘] GCD 최대공약수, LCM 최소공배수 (0) | 2019.11.24 |