| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 타입 스크립트
- 다음에 또 만나자
- 생일축하해 나 자신
- 뽀모도로 타이머
- 플러터
- 에러 핸들링
- 다행이야...ㅎ
- 자가격리
- 얘들아 잘 지내니
- 정보처리기사 2022
- FLUTTER
- pem키 분실
- 대학생
- 교수님 과제 이제 그만..
- 정보처리기사2022
- 2022 정보처리기사
- 리눅스 마스터 2급
- 수제비 2022
- 다들 안잊어서
- 교육봉사
- N-Queen
- CRUDS
- 아싸의 생일
- TypeScript
- 개강해짐
- 모바일 청첩장
- 수제비2022 정리
- 재택치료
- 스프링 MVC
- 지독한 컨셉충
- Today
- Total
Rei’s Tech diary
[최단 경로] 플로이드 워셜(Floyd-Warshall) 알고리즘 본문

💡 플로이드 워셜 (Floyd-Warshall) 알고리즘
- 모든 지점에서 다른 모든 지점까지의 최단 경로를 모두 구해야 하는 경우에 사용하는 알고리즘
- 그래프에 존재하는 모든 노드 쌍에 대한 최단 경로를 한번에 구할 수 있다.
- 노드의 갯수가 적을 경우에 사용한다.
- 2차원 리스트에 '최단 거리' 정보를 저장한다.
- 시간 복잡도 : $O(N^3)$
- 노드의 갯수가 N개일때, N번의 단계를 수행하며, 단계마다 $O(N^2)$의 연산을 통해 '현재 노드를 거쳐가는' 모든 경로를 고려한다.
💡 플로이드 워셜 알고리즘의 원리
- 각 단계에서는 '해당 노드를 거쳐가는 경우'를 고려한다.
예) 1번 노드에 대해서 1번 노드를 중간에 거쳐 지나가는 모든 경우를 고려한 루 최단 거리를 갱신한다.
A → B 로 가는 비용이 3일 때, A → 1번 노드 → B로 가는 비용이 2라는 것이 밝혀지면 A → B로 가는 비용을 2로 하는 갱신하는 것이다.
따라서, 알고리즘에서는 현재 확인하고 있는 노드를 제외하고 N - 1개의 노드 중에서 서로 다른 노드 (A, B) 쌍을 선택한 후 비용을 확인한 후에 최단 거리를 갱신한다.
점화식은 다음과 같다.
\[ D_{ab} = \min(D_{ab},\; D_{ak} + D_{kb}) \]
전체적으로 3중 반복문을 이용하려 이 점화식에 따라 최단 거리 테이블을 갱신하면 된다.

Step 0 )
연결된 간선 = 해당 값을 채워 넣음
연결되지 않은 간선 = 무한 값
| 출발 / 도착 | 1 | 2 | 3 | 4 |
| 1 | 0 | 4 | 무한 | 6 |
| 2 | 3 | 0 | 7 | 무한 |
| 3 | 5 | 무한 | 0 | 4 |
| 4 | 무한 | 무한 | 2 | 0 |
Step 1)
1 번 노드를 거쳐 가는 경우를 고려한다.
\[ D_{23} = \min(D_{23},\; D_{21} + D_{13}) \]
\[ D_{24} = \min(D_{23},\; D_{21} + D_{14}) \]
\[ D_{32} = \min(D_{32},\; D_{31} + D_{12}) \]
\[ D_{34} = \min(D_{34},\; D_{31} + D_{14}) \]
\[ D_{42} = \min(D_{42},\; D_{41} + D_{12}) \]
\[ D_{43} = \min(D_{43},\; D_{41} + D_{13}) \]
이 6가지 경우만 하나씩 확인하며 값을 계산하여 갱신한다.
| 출발 / 도착 | 1 | 2 | 3 | 4 |
| 1 | 0 | 4 | 무한 | 6 |
| 2 | 3 | 0 | 7 | 9 |
| 3 | 5 | 9 | 0 | 4 |
| 4 | 무한 | 무한 | 2 | 0 |
해당 과정을 마지막 노드까지 반복하면 된다.
<결과>
| 출발 / 도착 | 1 | 2 | 3 | 4 |
| 1 | 0 | 4 | 8 | 6 |
| 2 | 3 | 0 | 7 | 9 |
| 3 | 5 | 9 | 0 | 4 |
| 4 | 7 | 11 | 2 | 0 |
💡 플로이드 워셜 알고리즘 구현
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class FloydWarshallPractice {
static final int INF = (int) 1e9;
static int n, m;
static int[][] graph;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
m = Integer.parseInt(br.readLine());
graph = new int[n + 1][n + 1];
for(int i = 0; i <= n; i++){
Arrays.fill(graph[i], INF);
}
for(int a = 1; a <= n; a++) {
for(int b = 1; b <= n; b++) {
if(a == b) graph[a][b] = 0;
}
}
for(int i = 0; i < m; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
graph[a][b] = c;
}
for(int k = 1; k <= n; k++) {
for(int a = 1; a <= n; a++) {
for(int b = 1; b <= n; b++) {
graph[a][b] = Math.min(graph[a][b], graph[a][k] + graph[k][b]);
}
}
}
for(int a = 1; a <= n; a++) {
for(int b = 1; b <= n; b++) {
if(graph[a][b] == INF) {
System.out.print("INFINITY");
}else {
System.out.print(graph[a][b] + " ");
}
}
System.out.println();
}
}
}
참고 )
이것이 취업을 위한 코딩 테스트다 with 파이썬 | 나동빈 - 교보문고
이것이 취업을 위한 코딩 테스트다 with 파이썬 | IT 취준생이라면 누구나 입사하고 싶은 카카오ㆍ삼성전자ㆍ네이버ㆍ라인! 취업의 성공 열쇠는 알고리즘 인터뷰에 있다!IT 취준생이라면 누구나
product.kyobobook.co.kr
'프로그래밍 > Algorithm' 카테고리의 다른 글
| [그래프] 위상 정렬 (Topology Sort) (3) | 2025.08.02 |
|---|---|
| [그래프] 크루스칼(Kruskal) 알고리즘 (최소 신장 트리) (2) | 2025.08.02 |
| [최단 경로] 다익스트라(Dijkstra) 알고리즘 (4) | 2025.07.31 |
| 📊그래프의 두 가지 표현 방식 (인접 행렬 vs 인접 리스트) (5) | 2025.07.24 |
| [Java] Comparable vs Comparator 정리 (2) | 2025.07.14 |