1. 플로이드-워셜(Floyd-Warshall) 알고리즘이란?
모든 최단 경로를 구하는 알고리즘
다익스트라 알고리즘과는 다르게 음의 간선도 사용할 수 있다.
2. 동작방식
모든 노드간의 최단거리를 구하는 것이므로 2차원 인접 행렬을 구성한다.
각 경로의 중간 노드를 선택하여, 거리를 더 짧게 줄이는 과정을 반복한다.
초기 그래프를 인접형렬로 나타내면 아래와 같다.
INF는 해당 노드에서 특정노드까지 가는 길이 없음을 의미한다.
시작/끝 | 0 | 1 | 2 | 3 |
0 | 0 | 5 | INF | 1 |
1 | INF | 0 | 7 | 2 |
2 | 3 | INF | 0 | INF |
3 | INF | INF | 6 | 0 |
1) 1번 노드를 중간 노드로 설정할 경우
① 값이 변경될 경우
dist[0][2] = min(dist[0][2], dist[0][1] + dist[1][2]) = min(INF, 5 + 7 = 12) = 12
② 값이 변경되지 않을 경우
dist[0][3] = min(dist[0][3], dist[0][1] + dist[1][3]) = min(1, 5 + 2 = 7) = 1
시작/끝 | 0 | 1 | 2 | 3 |
0 | 0 | 5 | ✔ 12 | 1 |
1 | INF | 0 | 7 | 2 |
2 | 3 | INF | 0 | INF |
3 | INF | INF | 6 | 0 |
2) 2번 노드를 중간 노드로 설정할 경우
dist[1][0] = dist[1][2] + dist[2][0] = 7 + 3 = 10
dist[3][0] = dist[3][2] + dist[2][0] = 6 + 3 = 9
시작/끝 | 0 | 1 | 2 | 3 |
0 | 0 | 5 | 12 | 1 |
1 | ✔ 10 | 0 | 7 | 2 |
2 | 3 | INF | 0 | INF |
3 | ✔ 9 | INF | 6 | 0 |
이런식으로 0번노드, 3번노드가 중간값일때도 계속해서 업데이트해준다.
최종 값들은 아래와 같다. (변경된 값들은 주황색으로 표시)
시작/끝 | 0 | 1 | 2 | 3 |
0 | 0 | 5 | 7 | 1 |
1 | 10 | 0 | 7 | 2 |
2 | 3 | 8 | 0 | 4 |
3 | 9 | 14 | 6 | 0 |
3. 시간 복잡도
이 알고리즘은 3중 for문으로 수행되기 때문에 시간복잡도는 O(|V|^3)이다.
모든 정점 쌍의 최단 거리를 구하기 때문에, 다익스트라 알고리즘은 O(|V| |E| log |V) 이므로, 다익스트라가 약간 더 빠르다.
벨만-포드의 경우에는 O(|V|^2 |E|)이고, 보통 정점의 수보다 간선의 수가 더 많기 때문에 플로이드-워셜이 조금 더 빠르다고 볼 수 있다.
4. 파이썬 구현 코드
m은 중간 노드
E는 노드의 개수이다.
for문에는 i, j를 통해 각 노드별 모든 거리를 살펴보면서 k를 중간 노드로 삼을 때와 아닐 때의 값을 비교해 더 작은 값으로 변경해준다.
# dist[i][i]에는 0이, 경로가 없는 값에는 INF가 있다는 가정하에
for m in range(1,N+1):
for i in range(1,N+1):
for j in range(1,N+1):
dist[i][j] = min(dist[i][j], dist[i][m]+dist[m][j])
📖 reference
'코테 공부 🔥 > 보충 공부 🔠' 카테고리의 다른 글
[자료구조/Python] 세그먼트 트리(Segment Tree) (0) | 2023.03.24 |
---|---|
[알고리즘/Python] 분할 정복(Divide and Conquer) (0) | 2023.03.24 |
[알고리즘/Python] 이진 탐색(Binary Search) (1) | 2023.01.28 |
[Python] 파이썬 딕셔너리 값 정렬 (key, value) (0) | 2023.01.24 |
[Python] 파이썬 괄호 없이 리스트 출력 (0) | 2023.01.14 |
댓글