최소 신장 트리(Minimum Spanning Tree)
- 신장 트리
- 가중 무방향 그래프에서 모든 정점을 포함하는 트리
- 최소 신장 트리
- 신장 트리 중 간선 가중치의 합이 가장 작은 트리
- 그래프 G=(V,E) 에 대해, 트리 G′=(V′,E′)는 V′=V, E′⊆E
크루스칼 알고리즘
- 간선이 하나도 없는 상태에서 시작해서 가중치가 가장 작은 간선부터 하나씩 골라서 사이클을 형성하지 않으면 해당 간선을 추가하는 방식
- 간선 (u,v)의 두 정점 u,v가 서로 다른 연결 성분에 속하면 해당 간선은 사이클을 형성하지 않음
- |V|=n개의 정점이 각각의 서로 다른 연결 성분으로 구성된 상태에서 시작해서 간선을 추가할 때마다 연결 성분들이 하나씩 합쳐지고 최종적으로 하나의 연결 성분을 형성함
과정
- 그래프의 모든 간선을 가중치 기준으로 오름차순 정렬
- 제일 작은 간선부터 하나씩 선택
- 선택할 때마다
- 사이클이 생기는지 확인
- 사이클이 생기지 않으면 간선 추가
- 사이클이 생기면 버림
- 간선이 정점수 − 1개 가 되면 끝낸다
Kruskal(G):
T = ∅
for each vertex v in G:
정점 v로 구성된 연결 성분 초기화
가중치가 증가하는 순으로 모든 간선을 정렬
for each edge (u, v) in G.E (가중치가 가장 작은 것부터):
if u와 v가 서로 다른 연결 성분에 속하면:
T = T ∪ {(u, v)}
u가 속한 연결 성분과 v가 속한 연결 성분을 합침
else:
간선 (u, v)를 버림
return T
성능
- 연결 성분 초기화: MAKE-SET(v) 를 V번 호출 → O(V)
- 간선 정렬: O(E log E)
- for (모든 간선 (u,v) 에 대해)
→ E번 반복
→ 각 iteration 마다 FIND/UNION 비용 O(log E) → 전체 O(E log E) - 전체 시간 복잡도: O(E log E) ≈ O(E log V)
프림 알고리즘
- 임의의 한 정점에서 시작해서 연결된 정점을 하나씩 선택해나가는 방법
- 이미 선택된 정점들에 부수된 가중치가 가장 작은 간선을 선택해서 추가
과정
- 시작 정점 선택
- 임의의 정점 r 선택
- 선택된 정점 집합 S = {r}, MST 간선 집합 T = ∅
- 반복 (|S| < |V| 동안)
- S 와 V–S 를 잇는 모든 간선 중 최소 가중치 간선 (u,v) 선택
- T ← T ∪ {(u,v)}
- S ← S ∪ {v}
- 종료 조건
- |S| = |V| 이 되면 MST 완성 → T 반환
Prim(G):
T = ∅
S = {1} // 임의의 시작 정점(예: 1)으로 초기화
while S ≠ V:
// S 안의 정점 u와 S 밖의 정점 v를 잇는 최소 가중치 간선 (u, v) 선택
(u, v) = argmin { w(u,v) | u ∈ S, v ∈ V–S }
T = T ∪ {(u, v)}
S = S ∪ {v}
return T
성능
- 인접 행렬 사용 시: O(|V|²)
- 인접 리스트 + 힙(우선순위 큐) 사용 시: O((|V| + |E|) · log |V|)
최단경로 문제
- 가중 그래프에서 두 정점 u→v를 잇는 경로 중 간선 합이 최소인 경로
- 단일 출발점 최단경로: 데이크스트라, 벨만-포드 알고리즘
- 모든 상 최단 경로: 플로이드 알고리즘
데이크스트라(Dijkstra) 알고리즘
- 단일 출발점 최단 경로 알고리즘 → 하나의 출발 정점에서 다른 모든 정점으로 최단 경로를 찾는 알고리즘
- Greedy 방법이 적용: 매 단계 “가장 가까운” 미선택 정점부터 고정
- 음의 가중치 간선이 없는 그래프에만 적용 가능
- 거리 배열 d[v]: 출발점에서 S(선택된 정점 집합)를 거쳐 v까지의 현재까지 알려진 최단 거리
과정
- 초기화
- 출발 정점 s의 거리는 0 → d[s] = 0
- 나머지 모든 정점의 거리는 무한대 → d[v] = ∞
- 방문한 정점 집합 S = {} (아직 아무것도 확정 안 됨)
- 반복 (방문 안한 정점 중 제일 가까운 애부터)
- 아직 확정되지 않은 정점들 중, d[v] 값이 가장 작은 정점 u를 선택
- 정점 u는 이제 최단 경로가 확정되므로 S에 추가
- u와 인접한 모든 정점 v에 대해
- d[u] + W(u,v) < d[v]라면
- d[v]를 갱신하고,
- prev[v] = u로 경로 추적 정보를 저장
- 종료
- 모든 정점이 S에 포함되면 d[]에 최단 거리 확정
- d[v]: 출발 정점 s에서 v까지의 최단 거리
- prev[v]: v로 가는 최단 경로에서 직전 정점
// 입력: G = (V, E), s : 시작 정점
// 출력: d[] : s로부터 모든 정점까지의 최단 경로 길이
// prev[] : 최단 경로 추적을 위한 선행 정점
Dijkstra(G, s)
{
S = ∅;
d[s] = 0;
for (모든 정점 v ∈ V) {
d[v] = ∞;
prev[v] = NULL;
}
while (S ≠ V) {
// S에 포함되지 않은 정점 중 d[u]가 최소인 정점 u 선택
u ∈ V–S 중 d[u] 최소인 정점 선택;
S = S ∪ {u};
// u에 인접한 모든 정점 v에 대해 이완 처리
for (u에 인접한 모든 정점 v) {
if (d[v] > d[u] + W(u, v)) {
d[v] = d[u] + W(u, v);
prev[v] = u;
}
}
}
return (d[], prev[]);
}
성능
- 인접 행렬 사용: O(|V|²)
- 인접 리스트 + 우선순위 큐(힙) 사용: O((|V| + |E|) log |V|)
'알고리즘' 카테고리의 다른 글
그래프(1) - DFS, BFS, 위상정렬, 연결성분, 강연결성분 (0) | 2025.04.29 |
---|---|
탐색&해싱 (0) | 2025.04.24 |
정렬(3) - 힙, 계수, 기수, 버킷 (0) | 2025.03.27 |
정렬(2) - 퀵정렬, 합병정렬 (0) | 2025.03.23 |
정렬(1) - 선택, 삽입, 버블, 셸 (0) | 2025.03.16 |