그리디 알고리즘 - 최소 신장 트리
최소신장 트리에서 크루스칼과 프림을 알아보자
MST(최소 신장 트리)
정점(vertex)의 집합 V와 가중치를 갖는 에지(edge)의 집합 E로 구성된 그래프 G = <V,E>가 주어질때,
모든 정점을 연결하고 연결된 에지의 가중치 합이 최소인 트리
- 사이클X
- 예를 들어 상수도관 네트워크 설계의 경우 모든 사람에게 수돗물이 전달되어야 하고 전체 상수도관의 길이는 최소가 되는 것이 좋다.
최소 신장 트리 T를 구하는 그리디 알고리즘
- 그래프 G의 모든 에지를 최소 힙 H에 추가합니다
- H로부터 에지 e를 하나 꺼냅니다.(모든 에지중에서 가장 가중치가 작은 에지)
- e의 양 끝 정점이 이미 T에 있을경우, e로 인해 T에서 사이클이 발생할 수 있다, 그러므로 이런경우 e를 버리고 2단계로 이동
- 최소 신장 트리 T에 e를 추가하고 2단계로 이동
⇒ 2단계부터 4단계까지를 반복하면서 가장 작은 가중치의 에지를 찾고, 이 에지에 의해 사이클이 발생하지 않으면 해당 에지와 양 끝 정점을 최종 솔루션에 추가한다.
크루스칼 MST 알고리즘 구현 방법
3단계가 좀 복잡 : 그래프 에지 정보를 저장할 자료 구조가 필요하고, 새로운 에지를 추가할 때 사이클이 발생하는지를 판단하는 기능이 필요
이 문제는 디스조인트-셋 자료구조로 해결 가능
디스조인트-셋 자료 구조 (union-find)
- 디스조인트-셋 또는 유니온-파인드 자료구조는 트리 형태의 원소로 구성된 포레스트(트리들의 집합)이다.
- 각각의 원소는 1. 숫자 ID에 의해 표현되며, 2. 랭크(rank)와 부모에 대한 포인터를 가진다.
- 이 자료구조가 초기화 되면 랭크가 0인 N개의 독립적인 원소가 생성됨, 각각의 원소는 하나의 트리를 나타냄
이 자료구조가 지원하는 연산
- make-set(x) : x를 ID로 갖는 원소를 유니온-파인드 자료구조에 추가한다.
- 처음 추가하면 그 원소의 랭크는 0
- 원소의 부모 포인터는 자기 자신
i는 노드 번호 p[i]는 부모 노드 번호
- find(x) : 원소 x에서 시작해서 부모 포인터를 따라 반복적으로 이동하여 트리의 루트를 반환한다.
- union(x, y)
- 두 개의 원소 x와 y에 대해 union()연산을 수행하면 x와 y의 루트를 찾는다.
- 만약 두 루트가 같다면 x와 y가 같은 트리에 속해 있음을 의미 ⇒ 아무런 작업X
-
만약 두 루트가 다르다면 높은 랭크 루트를 낮은 랭크 루트의 부모로 설정
1
2
3
4
5if(nodes[root_x].rank > nodes[root_y].rank){ swap(root_x,root_y); //nodes[root_y].parent = nodes[root_x].parent; 같은 의미 } nodes[root_x].parent = nodes[root_y].parent;
계속 연산을 거듭할수록 더 많은 트리가 병합되어 전체 트리 개수는 줄어들고, 대신 각 트리의 크기는 점점 거대해짐
다시 돌아와서 이 유니온-파인드 자료구조를 사용하여 크루스칼 MST 알고리즘을 구현해보자
- 그래프 정점 개수가 N이라면, 먼저 N개의 원소를 갖는 디스조인트-셋 자료 구조를 초기화
- 사이클 발생 여부를 판단(MST 3단계)해야 한다고 했는데 union(x,y)연산을 활용
- 두 트리를 병합하여 MST 4단계 수행
- x와 y의 루트가 같다는 것은 사이클이 발생한다는 뜻 ⇒ 그래서 union연산 종료
1 |
|
프림 MST 알고리즘
프림 알고리즘은 BFS의 동작 방식과 유사
- 시작 정점을 이용하여 경계를 구성
- 현재 경계에 인접한 정점을 반복적으로 탐색, 그중 가중치가 가장 작은 에지를 선택하고, 이 에지에 연결된 정점을 방문
각 정점에 경계로부터의 거리 정보를 기록해야 함
- 모든 정점의 거리 값을 무한대로 초기화, 시작정점은 자기 자신까지의 거리는 0이므로 시작정점의 거리값은0 그리고 모든 거리값을 최소 힙 H에 추가
- 최소 힙 H로부터 정점을 하나 꺼낸다(U)(경계에서 가장 가까운 정점) 이 정점을 MST에 추가하고, 이 정점을 포함하도록 경계를 새로 설정
- U와 인접한 모든 정점 V에 대해, 만약 V의 거리값이 (U, V)의 에지 가중치보다 크면 V의 거리값을 (U, V)의 에지 가중치로 설정
- 방문하지 않은 정점이 남아 있다면 2단계로 이동