최소 스패닝 트리
Prim(프림), Kruskal(크루스칼) 알고리즘
+ Union-Find 자료구조
* 개요
- 신장 트리(스패닝 트리, Spanning Tree)란?
1. 그래프의 모든 정점이 간선으로 연결되어 있다.
2. 그래프 안에 사이클이 포함되어 있지 않다.
- 최소 신장 트리(최소 스패닝 트리, Minimum Spanning Tree)란?
말그대로 최소 비용으로 만들어진 신장 트리. 가중치의 합이 가장 작은 신장 트리
- 프림과 크루스칼 알고리즘은 최소 스패닝 트리를 구하는 방법 중 하나이다.
- 둘 다 Greedy Method을 기초로 하고 있다. (당장 눈앞의 최소 비용의 선택을 해서 결과적으로 최적의 Solution을 찾는다.)
- 프림은 정점 위주의 알고리즘, 크루스칼은 간선 위주의 알고리즘이다.
- 프림은 시작점을 정하고, 시작점에서 가까운 정점을 선택하면서 MST를 구성하므로 그 과정에서 사이클을 이루지 않지만
- 크루스칼은 시작점을 정하지 않고, 최소 비용의 간선을 차례로 대입하면서 MST를 구성하므로, 그 과정에서 사이클을 이루는지 항상 확인해야 한다. 사이클을 확인하는 방법으로는 Union-Find(Disjoint-Set) 방법이 있다.
- 시간 복잡도는 비슷하지만, 일반적으로 Dense한 그래프의 경우 프림이, 그렇지 않은 경우에는 크루스칼이 유리하다.
- 프림의 경우 최소 거리의 정점을 찾는 부분에서 자료구조의 성능에 영향을 받는다.
- 크루스칼은 간선을 weight 기준으로 정렬하는 과정이 오래 걸린다.
- 프림 : O(V^2+E) → O(E logV)
- 크루스칼 : O(E logE)
1. Prim's Algorithm (프림)
https://ko.wikipedia.org/wiki/%ED%94%84%EB%A6%BC_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
2. Kruskal Algorithm (크루스칼)
https://ko.wikipedia.org/wiki/%ED%94%84%EB%A6%BC_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
크루스칼 알고리즘은 아래 링크에서도 설명이 잘 되어 있습니다.
http://navercast.naver.com/contents.nhn?rid=2871&contents_id=86840
+ Union-Find 자료구조
( = Disjoint - Set 자료구조)
위 개요에서 크루스칼 알고리즘의 경우,
간선을 추가할 때마다 트리가 사이클을 이루는지 판단해야 한다고 했습니다.
이 때 활용할 수 있는 자료구조가 바로 Union-Find 자료 구조입니다.
이름에서 볼 수 있는 것처럼, Union 연산과 Find 연산이 가능합니다.
아래와 같은 그래프가 있다고 생각해봅시다.
현재 정점 0, 1, 2, 3이 연결되어 있고, 정점 4, 5, 6이 서로 연결되어 있습니다.
위 그래프를 아래와 같이 표현해 봅시다. 이렇게 표현하면
정점 0, 1, 2, 3은 정점 0의 그룹,
정점 4, 5, 6은 정점 4의 그룹이라는 것을 쉽게 알 수 있습니다.
1) root 배열
int[] root = new int[7]; 배열을 선언합시다.
root 배열의 값은 각 정점의 root를 나타냅니다. 그리고 각 그룹의 리더는 음수값을 갖습니다. (초기값이 -1이고 그룹이 커질수록 더 작아짐)
root[0] = -4
root[1] = 0, root[2] = 0, root[3] = 0
root[4] = -3
root[5] = 4, root[6] = 4
즉, 두 정점이 같은 그룹인지 확인하려면 각각의 정점의 root 노드를 구한 뒤 비교하면 되겠죠?
2) find 연산
위와 같이 각 정점의 root 노드를 알아내는 연산이 바로 find연산입니다.
- a 정점의 root배열 값이 음수라면, 즉 자기가 root 노드이므로 a 자신을 리턴합니다.
- a 정점의 root배열 값이 음수가 아니라면, 재귀적 함수 호출로 root 노드를 찾습니다. 그리고 root[a]의 값을 갱신함으로써, 깊은 depth의 여러 정점들을 모두 root 노드 한단계 아래에 두게 됩니다.
예) 3번 정점과 5번 정점이 같은 그룹인가?
if ( find(3) == find(5) ) {
// 같은 그룹이다.
}
else {
// 다른 그룹이다.
}
3. Union 연산
* 전체 코드
* 대표 문제
http://stack07142.tistory.com/53
'Algorithm > 기타' 카테고리의 다른 글
[수학] 두 선분의 교차 여부 확인하기 (1) | 2017.03.08 |
---|---|
벨만-포드 알고리즘(Bellman-Ford algorithm) (0) | 2017.01.09 |
Dynamic Programming, 동적계획법 (0) | 2016.12.04 |
Dijkstra 다익스트라 알고리즘 (우선순위 큐를 사용하지 않는) (0) | 2016.12.04 |
B-Tree (0) | 2016.11.07 |