16. 다익스트라 알고리즘 : O(V2)
2020 AL林 정기 스터디 16
while (모든 점을 탐색할 때까지) {
1. u = (시작점에서 가장 가까운 노드)
2. u와 인접한 정점에 대해서 최단경로를 갱신한다.
}
17. 다익스트라 알고리즘 : O(V2)
2020 AL林 정기 스터디 17
더 구체적으로 봅시다.
s : 시작점, weight[][] : 가중치 인접 행렬
distance = [∞, ∞, ..., ∞]
found = [False, False, ..., False]
distance[s] = 0
found[s] = True
for (s에 인접한 정점 u에 대해서) {
distance[u] = weight[s][u]
}
18. 다익스트라 알고리즘 : O(V2)
2020 AL林 정기 스터디 18
더 구체적으로 봅시다.
for (V – 1번 반복) {
u = (found[u]가 False이면서 distance가 가장 작은 정점)
found[u] = True
for (u에 인접한 정점 v에 대해서) {
if (distance[v] > distance[u] + weight[u][v])
distance[v] = distance[u] + weight[u][v])
}
}
return distance
23. 다익스트라 알고리즘 : O(ElogV)
2020 AL林 정기 스터디 23
간선의 수가 적은 경우를 최적화 해봅시다.
필요한 것
1. 인접 행렬 → 인접 리스트
2. 최소 힙
24. 다익스트라 알고리즘 : O(ElogV)
2020 AL林 정기 스터디 24
while (모든 점을 탐색할 때까지) {
1. u = (시작점에서 가장 가까운 노드)
2. u와 인접한 정점에 대해서 최단경로를 갱신한다.
}
25. 다익스트라 알고리즘 : O(ElogV)
2020 AL林 정기 스터디 25
s : 시작점, weight[][] : 가중치 인접 리스트, priority_queue : 최소 힙
distance = [∞, ∞, ..., ∞]
found = [False, False, ..., False]
distance[s] = 0
found[s] = True
priority_queue ← {0, s} // {거리, 정점 번호}
26. 다익스트라 알고리즘 : O(ElogV)
2020 AL林 정기 스터디 26
while (priority_queue is not empty) {
u = priority_queue.pop() // 시작점에서 가장 가까운 정점
if (found[u] = True) continue;
found[u] = True
for (u에 인접한 정점 v에 대해서) {
w ← (u, v)의 가중치
if (distance[v] > distance[u] + w){ // 최단경로 갱신
distance[v] = distance[u] + w
priority_queue.push( {distance[v], v} )
}
}
}
27. 다익스트라 알고리즘 : O(ElogV) 소스코드
2020 AL林 정기 스터디 27
C++ : http://boj.kr/9a87325c505a4a069f7236395065d501
python : http://boj.kr/e791640f89d649adbb6fabe51f196fd5
30. 음의 가중치
2020 AL林 정기 스터디 30
다익스트라 알고리즘은 음의 가중치가 있으면 작동하지 않습니다.
다익스트라 알고리즘에서
어떤 정점을 방문한 이후에도 더 짧은 경로가 존재할 수 있기 때문입니다.
31. 음의 사이클
2020 AL林 정기 스터디 31
e
s
-8
3
4
1
3
“음의 사이클이 있는 경우 최단 경로를 구할 수 없습니다.”
32. 벨만-포드 알고리즘(Bellman–Ford algorithm)
2020 AL林 정기 스터디 32
음의 간선을 허용하는 최단 경로 알고리즘
최단 거리 distance[v]와 distance[u]에 대해서 다음은 항상 참입니다.
distance[v] <= distance[u] + w(u, v)
33. 벨만-포드 알고리즘(Bellman–Ford algorithm)
2020 AL林 정기 스터디 33
음의 간선을 허용하는 최단 경로 알고리즘
간선 1개를 사용한 최단 경로
간선 2개를 사용한 최단 경로
...
간선 m개를 사용한 최단 경로 (m는 최대 V - 1)
를 구합니다. 총 시간복잡도는 O(VE) - 인접 리스트 / O(V3) - 인접 행렬
34. 벨만-포드 알고리즘
2020 AL林 정기 스터디 34
s : 시작점
distance = [∞, ∞, ..., ∞]
distance[s] = 0
for (V – 1번 반복) {
for (모든 간선 w(u, v)에 대해서) {
if (distance[v] > distance[u] + w(u,v))
distance[v] = distance[u] + w(u,v)
}
}
35. 벨만-포드 알고리즘
2020 AL林 정기 스터디 35
// 음의 사이클 존재 여부 확인
for (모든 간선 w(u, v)에 대해서) {
if (distance[v] > distance[u] + w(u,v))
output “음의 사이클 존재”
}
return distance
38. 벨만-포드 알고리즘 : 정당성
2020 AL林 정기 스터디 38
1. 왜 최대 V – 1개의 간선만을 이용하면 되는가?
2. m번 루프를 수행하면 m개의 간선을 이용한
최단 경로가 구해지는가?
위 두개의 정당성을 증명하면
V – 1번의 루프로 완성된 경로는 최단경로입니다.
자세한 정당성은 뒤 슬라이드를 참고하세요.
41. 플로이드-워샬 알고리즘
2020 AL林 정기 스터디 41
벨만-포드 알고리즘을 확장해봅시다.
벨만-포드는 한 시작점에 대해서 O(V3)에 최단 경로를 구할 수 있습니다.
따라서 모든 최단 경로는 O(V4)에 구할 수 있습니다.
42. 플로이드-워샬 알고리즘
2020 AL林 정기 스터디 42
모든 최단 경로를 O(V4)에 구하는 알고리즘
dij
m : 최대 m개의 간선을 사용해서 i에서 j이 이르는 거리
for (V – 1번 반복)
for (i ← 1 to V)
for (j ← 1 to V)
for (k ← 1 to V)
dij
m = min(dij
m, dik
m-1 + wkj)
43. 플로이드-워샬 알고리즘
2020 AL林 정기 스터디 43
여기서 d를 수정해봅시다.
dij
k : 집합 {1, 2, 3, ..., k}에 속하는 정점만 거쳐서 i에서 j에 이르는 최단 거리
이 때, dij
k = min(dij
k-1, dik
k-1+ dkj
k-1)가 성립합니다.
i
k
j
중간 정점이 모두 {1, 2, ..., k-1}에 속함
44. 플로이드-워샬 알고리즘
2020 AL林 정기 스터디 44
모든 최단 경로를 O(V3)에 구하는 알고리즘(플로이드-워샬)
dij
k : 집합 {1, 2, 3, ..., k}에 속하는 정점만 거쳐서 i에서 j에 이르는 최단 거리
for (k ← 1 to V)
for (i ← 1 to V)
for (j ← 1 to V)
dij
k = min(dij
k-1, dik
k-1 + dkj
k-1)
46. 플로이드-워샬 알고리즘 : 정당성
2020 AL林 정기 스터디 46
dij
k = min(dij
k-1, dik
k-1+ dkj
k-1)가 정말 성립 할까요? (최단 경로일까요?)
자세한 정당성은 뒤 슬라이드를 참고해주세요.
i
k
j
중간 정점이 모두 {1, 2, ..., k-1}에 속함
48. 무방향 그래프에서 최단 경로
2020 AL林 정기 스터디 48
무방향 그래프에서 u와 v가 연결되어있다는 것은
두 간선이 있다는 것과 같습니다. (u → v), (v → u)
음의 가중치가 없는 경우 : 오늘 배운 최단 경로 알고리즘을 쓰면 됩니다.
음의 가중치가 있는 경우 : 음의 사이클이 있으므로 최단 경로를 구할 수 없습니다.
49. 이전 경로
2020 AL林 정기 스터디 49
최단 거리는 알았는데 경로는 어떻게 알 수 있을까요?
최단 경로를 갱신할 때, 이전 노드를 저장하는 배열에 저장하면 됩니다.
if (distance[v] > distance[u] + w){ // 최단경로 갱신
distance[v] = distance[u] + w
prev[v] = u
priority_queue.push( {distance[v], v} )
50. 음의 사이클이 한 컴포넌트에 있는지 잘 확인합시다.
2020 AL林 정기 스터디 50
음의 사이클이 있어도 도달할 수 없으면 상관 없겠죠?
연습문제 : 타임머신 (BOJ 11657)
e
s
-8
3
4
1
3
51. 플로이드-워샬 알고리즘 자주하는 실수
2020 AL林 정기 스터디 51
for문 순서가 k → i → j 입니다.
i → k → j 또는 i → j → k로 하지 맙시다.
위 알고리즘을 이해하셨으면 아시겠지만 최단 경로가 나올 수 없습니다.
for (k ← 1 to V)
for (i ← 1 to V)
for (j ← 1 to V)
dij
k = min(dij
k-1, dik
k-1 + dkj
k-1)
52. 최단 사이클을 찾는 방법
2020 AL林 정기 스터디 52
플로이드-워샬 알고리즘을 잘 활용해봅시다.
연습문제 : 운동 (BOJ 1956)
https://www.acmicpc.net/problem/1956
53. 플로이드-워샬 vs 다익스트라
2020 AL林 정기 스터디 53
단일 시작점에 대해서만 구할 경우 : 다익스트라가 우수
모든 쌍을 구할 경우 : 간선의 수에 따라 다르다.
플로이드-워샬 시간복잡도 : O(V3) 공간복잡도 : O(V2)
다익스트라 시간복잡도 : O(V * ElogV) 공간복잡도 : O(V+E) - 인접리스트
O(V2) - 인접행렬
플로이드–워샬은 음의 간선도 허용한다.
54. 플로이드-워샬 vs 벨만-포드
2020 AL林 정기 스터디 54
단일 시작점인 경우 : 인접 리스트를 사용한 벨만-포드가 우수 → 시간복잡도 O(VE)
간선이 적을수록 효율적이다.
간선이 많아지면 점점 시간복잡도가 O(V3)에 가까워진다.
모든 쌍을 구할 경우 : 플로이드-워샬이 우수
56. DAG에서의 최단 경로 알고리즘
2020 AL林 정기 스터디 56
1. 위상 정렬을 한다.
2. 위상 정렬 순서대로 다음을 반복한다.
u에 인접한 정점에 대해서 최단 경로를 갱신한다.
위상 정렬 : O(V + E)
최단 경로 : O(V + E)
57. 최장 경로 문제
2020 AL林 정기 스터디 57
다익스트라에서 가장 긴 경로 먼저 탐색하면 될까요?
아닙니다. 이 문제는 NP-Hard 문제입니다.
58. Meet in the middle
2020 AL林 정기 스터디 58
양방향 BFS(Bidirectional BFS)라는게 있습니다.
BFS는 쉽게 됩니다.
s e
59. Best first search
2020 AL林 정기 스터디 59
다익스트라 알고리즘은 Best first search의 기원입니다.
A* 알고리즘은 다익스트라 알고리즘에 휴리스틱이 더해진 탐색 알고리즘입니다.
탐색 알고리즘에 대해서 더 궁금하면 다음 서적을 참고하면 좋습니다.
Artificial Intelligence: A Modern Approach(AIMA), Stuart J. Russell, Peter Norvig
- 3. Solving Problems by Searching