가중치 그래프의 두 정점 사이의 거리 중 가장 최단거리는 어떻게 찾을 수 있을까?
이 문제를 해결하기 위해서는 모든 시작점으로부터의 최단 경로 정보가 필요하다.
그렇다면 다익스트라 알고리즘을 v번 호출하면 풀 수 있다.
단일 시작점 최단 경로 알고리즘 (다익스트라, 벨만 포드)
가중치 그래프에서 시작 정점 s에서 다른 정점들 사이의 최단 경로를 구해보자! 일단, 시작 정점 s에서 어떤 정점 v사이의 거리를 배열(distance[v])로 나타내 보자. 그러면 distance[s] = 0이라고 표현할
0923ulee.tistory.com
그렇지만 더 짧은 길이의 코드로 손쉽게 푸는 방법이 있다!
플로이드 워셜 알고리즘
가능한 모든 시작점(모든 정점)으로부터의 최단 경로 정보가 필요할 때 사용하는 알고리즘이다.
작은 그래프를 인접 행렬로 저장하고, 3중 for문을 사용해서 최단 거리를 구한다.
플로이드 워셜 알고리즘은 DP 알고리즘이다.
3중 for문을 사용하기에 O(V^3)의 시간이 걸린다. 따라서 그래프가 작을 때 사용하는 것을 추천한다.
(+) 주어진 그래프의 크기가 작다면 (V<=400)이 알고리즘을 사용하자!
코드는 아래와 같다.
void FloydWarshall() {
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
v[i][j] = min(v[i][j], v[i][k] + v[k][j]); //relax
}
}
}
}
안에 있는 2개의 for문은 선택된 두 정점(i,j)를 의미한다.
가장 큰 for문은 두 정점 사이에 있는 점 k를 선택해서, k를 통해 가는 경로가 더 짧은지 판단하기 위해 존재한다.
즉, relax하기 위한 점k를 찾기 위한 for문이다.
최단 경로를 구하기 위한 완화 작업(Relax)이란?시작 정점 s에서 v로 가는 경로에서, 간선 u->v를 사용하는 것이 이득인지 판단하는 검사이다.시작 정점 s에서 v로 가는 기존 경로와 시작 정점 s에서 정점 u를 지나 v로 가는 경로 중 더 짧은 거리를 선택한다는 의미이다. ![]() distance[v] = min(distance[v], distance[u] + weight(u->v)) //u를 거치는 방법으로 갱신이 일어난 경우 "완화했다"라고 표현한다. |
아래는 가중치 그래프의 두 정점 사이의 거리 중 가장 최단거리를 찾는 가장 기본적인 플로이드 워셜 문제이다.
https://www.acmicpc.net/problem/11404
11404번: 플로이드
첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가
www.acmicpc.net
'알고리즘 > 알고리즘 이론' 카테고리의 다른 글
Network Flow - 네트워크 플로우 (최대 유량 알고리즘) (0) | 2022.08.03 |
---|---|
Disjoint set, 분리 집합, Union-Find (0) | 2022.03.08 |
탐색 알고리즘(DFS, BFS)과 활용 (0) | 2022.03.05 |
냅색(Knapsack) 알고리즘 (0) | 2022.03.04 |
단일 시작점 최단 경로 알고리즘 (다익스트라, 벨만 포드) (1) | 2022.03.02 |