최단 경로 알고리즘 - 플로이드 워셜 알고리즘

728x90
반응형

https://www.youtube.com/watch?v=acqm9mM1P6o&t=831s 

플로이드 워셜 알고리즘 개요

  • 모든 노드에서 다른 모든 노드까지의 최단 경로를 모두 계산한다.
  • 플로이드 워셜(Floyd-Warshall) 알고리즘은 다익스트라 알고리즘과 마찬가지로 단계별로 거쳐 가는 노드를 기준으로 알고리즘을 수행한다.
    • 다만 매 단계마다 방문하지 않은 노드 중에 최단 거리를 갖는 노드를 찾는 과정이 필요하지 않다.
  • 플로이드 워셜은 2차원 테이블에 최단 거리 정보를 저장한다.
  • 플로이드 워셜 알고리즘은 다이나믹 프로그래밍 유형에 속한다.

플로이드 워셜은 점화식에 맞게 3중 반복문을 통해서 2차원 테이블을 갱신해주는 방식으로 동작한다. 다익스트라 알고리즘보다 구현 난이도는 쉽지만, 시간 복잡도는 O(N3)이라는 단점이 있다.

그렇기 때문에 노드의 갯수가 적을 때 효과적으로 사용할 수 있다.

 

플로이드 워셜 알고리즘의 점화식

  • 각 단계마다 특정한 노드 k 를 거쳐 가는 경우를 확인한다.
    • a에서 b로 가는 최단 거리보다 a에서 k를 거쳐 b로 가는 거리가 더 짧은지 검사한다.
  • 점화식은 다음과 같다.

 

[초기 상태] : 그래프를 준비하고 최단 거리 테이블을 초기화한다.

 

맨 처음에는 각 노드를 기준으로 현재 노드와 인접한 노드들을 확인하여 테이블을 갱신한다.

2차원 테이블을 이용해서 각 노드가 다른 노드로 가는 비용을 기록한다.

 

초기 상태에는 인접한 노드만 확인해서 테이블을 초기화 해준다. 이후에 각 노드에 대해서 거쳐가는 경우를 확인하여 테이블을 갱신해준다.

 

[1 단계] : 1번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다. (즉, k = 1)

 

1번 노드를 거쳐가는 경우를 고려하기 때문에 1번 노드의 행과 열 그리고 자기 자신의 최단 거리는 갱신되지 않는다.

 

그리고 1번 노드를 거쳐가는 6가지의 경우 기존의 비용과 1번 노드를 거쳐가는 비용을 비교하여 더 작은 값을 테이블에 저장한다.

 

[2 단계] : 2번 노드를 거쳐 가는 경우를 고려하여 테이블을 갱신한다.

 

마찬가지로 2번 노드를 거쳐가는 경우를 고려하기 때문에 2번 노드의 행과 열 그리고 자기 자신의 최단 거리는 갱신되지 않는다.

 

2번 노드를 거쳐가는 6가지의 경우 기존의 비용과 2번 노드를 거쳐가는 비용을 비교하여 더 작은 값을 테이블에 저장한다.

 

위 과정을 반복해서 전체 노드를 한바퀴 돈다.

 

플로이드 워셜 알고리즘 코드

INF = int(1e9)

n = int(input())
m = int(input())
# 2차원 리스트를 만들고 무한으로 초기화
graph = [[INF]*(n+1) for _ in range(n+1)]

# 자기 자신으로 가는 비용은 0으로 초기화
for a in range(1, n+1):
    for b in range(1, n+1):
        if a == b:
            graph[a][b] = 0

# 각 간선에 대한 정보를 입력 받아, 그 값으로 초기화
for _ in range(m):
    # a에서 b로 가는 비용 c
    a, b, c = map(int, input().split())
    graph[a][b] = c

# 점화식에 따라 플로이드 워셜 알고리즘 수행
for k in range(1, n+1):
    for a in range(1, n+1):
        for b in range(1, n+1):
            graph[a][b] = min(graph[a][b], graph[a][k] + graph[k][b])
            
# 수행된 결과를 출력
for a in range(1, n+1):
    for b in range(1, n+1):
        if graph[a][b] == INF:
            print("무한", end=" ")
        else:
            print(graph[a][b], end=" ")
    print()

플로이드 워셜 알고리즘 성능 분석

  • 노드의 개수가 N개일 때 알고리즘 상으로 N번의 단계를 수행한다.
    • 각 단계마다 O(N2) 의 연산을 통해 현재 노드를 거쳐 가는 모든 경로를 고려한다.
  • 따라서 플로이드 워셜 알고리즘의 총 시간 복잡도는 O(N3) 이다.
728x90
반응형