[알고리즘] 플로이드-워셜 알고리즘

권나연·2025년 1월 19일

알고리즘_개념

목록 보기
6/9
post-thumbnail

🔒 개념

🔎 각 노드부터 나머지 노드까지의 최단 경로를 모두 구하는 알고리즘

  • 모든 노드간 (모든 지점에서 다른 모든 지점까지)의 최단 거리를 구함
  • 음수 사이클이 없어야함 (음수 가중치는 허용)
  • 그래프 비용 인접 행렬로 표현되어 있다고 가정
  • 시간 복잡도 O(n^3)
  • 동적 계획법 이용
  • 출제 빈도 낮음.

🔓 동작 단계

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

  • 도출된 점화식은 :

📁 Step 1. 배열 선언 및 초기화

  • S, E의 값이 같은 칸은 0, 다른데는 INF로 초기화.

📁 Step 2. 최단 거리 배열에 그래프 데이터 저장

  • D[S][E] = W로 에지의 정보를 배열에 입력.
  • 인접 행렬로 표현!!

📁 Step 3. 점화식으로 배열 업데이트

  • 3중 for문의 형태로 배열의 값 업데이트.

📌 특징

  • '모든 지점에서 다른 모든 지점까지의 최단 경로를 모두 구해야 하는 경우'에 사용할 수 있는 알고리즘

  • 따라서 일반으로 노드 개수의 범위가 다른 그래프에 비해 적게 나타난다.

  • 플로이드 워셜 알고리즘 또한 단계마다 '거쳐 가는 노드'를 기준으로 알고리즘을 수행한다. 하지만, 매 단계마다 방문하지 않은 노드 중에서 최단 거리를 갖는 노드를 찾을 필요가 없다.

  • 플로이드 워셜은 2차원 테이블에 최단 거리 정보를 저장한다. (모든 지점에서 다른 모든 지점까지의 최단 거리를 저장해야 하기 때문)

  • 플로이드 워셜 알고리즘은 DP 알고리즘에 속한다. 왜냐하면 만약 노드의 개수가 N개라고 할 때, N번 만큼의 단계를 반복하며 '점화식에 맞게' 2차원 리스트를 갱신하기 때문에 DP라고 볼 수 있다.

⏰ 코드

import sys

input = sys.stdin.readline
INF = int(1e9)

# 노드의 개수(n)과 간선의 개수(m) 입력
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('INFINITY', end=' ')
        else:
            print(graph[a][b], end=' ')
    print()

# sample input
# 4
# 7
# 1 2 4
# 1 4 6
# 2 1 3
# 2 3 7
# 3 1 5
# 3 4 4
# 4 3 2
profile
백엔드 개발자 지망생 🍎

0개의 댓글