다익스트라, 벨만-포드 알고리즘으로 주어진 하나의 정점으로부터 다른 모든 정점들까지의 최단 경로를 구할 수 있었다면, 플로이드-워셜 알고리즘을 활용하면 모든 정점들간의 최단 경로
를 구할 수 있다.
다익스트라 알고리즘에서는 출발점이 정해져 있었기 때문에 출발점에서 도달할 수 있는 가장 가까운 경로를 탐욕적으로 선택해갔다. 그런데 출발점이 따로 정해져있지 않은 경우에는 어떨까?
플로이드-워셜 알고리즘은 경유하는 정점에 초점을 두고, 그 정점을 거쳐가는 경로가 기존 경로보다 더 효율적인지를 판단한다. 즉, 경유하는 정점의 입장에서 어떤 정점 u가 다른 정점 v로 갈 때 자신을 거쳐서 가는 것이 기존의 경로보다 더 효율적이라면 기존의 경로를 갱신해주는 작업을 반복하는 것이다.
def floyd_warshall(n, edges):
# 그래프 정보를 담을 인접행렬, 거리는 무한대로 초기화
adj = [[float('inf')] * (n+1) for _ in range(n+1)]
# 인접행렬에 그래프 정보 저장 (정점 u -> v 거리 w)
for u, v, w in edges:
adj[u][v] = w
# k : 경유지 (각 정점들을 경유지로 설정)
for k in range(1, n+1):
for i in range(1, n+1):
for j in range(1, n+1):
# 정점 i -> j로 갈 때 기존 거리값과 k를 거쳐갈 때의 거리 값 중 작은 값을 저장
adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j])
return adj
# 정점 개수 & 간선 정보
n = 4
edges = [[1, 2, 4],
[1, 3, 1],
[2, 3, 2],
[2, 4, 1],
[3, 2, 1],
[4, 1, 5],
[4, 3, 5]]
# 결과 출력
dist = floyd_warshall(n, edges)
for i in range(1, n+1):
print(dist[i][1:])
코드에서 알 수 있듯이 정점의 개수 만큼 반복분이 3중으로 수행되고 있기 때문에 의 시간 복잡도를 갖는다.
그리고 간선들의 정보를 크기의 인접행렬에 담았기 때문에 의 공간 복잡도를 갖는다.