Graph 를 활용한 Shortest Path (최단 경로) 구하기
그래프의 정점 간에 가장 짧은 거리를 구하는 알고리즘.
가중치 그래프에서 “짧다”는 의미는 가중치의 합이 최소라는 뜻임.
Shortest Path를 구하는 문제 유형에는 SSSP와 APSP가 있
| 유형 | 설명 | 대표알고리즘 |
| Single Source Shortest Path (SSSP) | 한 정점에서 모든 정점까지 최단 경로 찾기 | BFS, Dijkstra, Bellman–Ford |
| All Pair Shortest Path (APSP) | 모든 정점 쌍 간 최단 경로 찾기 | Floyd–Warshall |
1. Single Source Shortest Path
(1) BFS (가중치가 없는 경우)
가중치가 모두 1이거나 동일한 그래프에서는 BFS로 최단 경로를 구할 수 있음.
이유는 BFS가 가까운 정점부터 차례로 방문하기 때문.
== BFS는 가까운 정점부터 차례로 탐색하므로, 탐색 순서 자체가 최단 거리 순서가 됨.
- 가중치가 모두 동일할 때만 사용 가능
- 시간 복잡도: O(V + E)
- BFS 탐색 순서가 곧 최단 거리 순서임
처리과정
| queue 사용 | 방문처리방법 |
| 시작점에서 거리 0으로 시작 큐(Queue)에 넣고, 방문할 때마다 이전 거리 + 1로 업데이트 |
시작 정점의 거리를 0으로 두고 큐에 넣음 인접 정점을 방문할 때마다 거리 = 현재 거리 + 1 이미 방문한 정점은 다시 방문하지 않음 |
코드)
void shortestPathBFS(vector<int> adj[], int start, int V) {
vector<int> dist(V, -1);
queue<int> q;
dist[start] = 0;
q.push(start);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (dist[v] == -1) {
dist[v] = dist[u] + 1;
q.push(v);
}
}
}
for (int i = 0; i < V; i++)
printf("dist[%d] = %d\n", i, dist[i]);
}
(2) Dijkstra’s Algorithm (다익스트라 알고리즘)
가중치가 양수인 그래프에서 가장 짧은 거리를 효율적으로 구함.
Greedy(탐욕적) 접근으로, 매번 현재까지 가장 짧은 거리의 정점을 선택함.
== "방문하지 않은 정점 중, 현재까지 가장 짧은 거리인 정점을 선택하고
그 정점과 인접한 정점들의 거리를 갱신한다."
- 가중치가 모두 양수일 때만 사용 가능 (음수 가중치 X)
- 시간 복잡도: O(V²) (배열 기반) / O(E log V) (Heap 기반)
- 빠르고 직관적이지만 음수 간선이 있으면 오작동 함.
다익스트라 알고리즘 :: 바바썬 <- 자세한 내용은 과거 정리 내용 참고
처리과정
- 시작 정점의 거리를 0으로 초기화
- 나머지 정점은 ∞ (무한대)로 설정
- 방문하지 않은 정점 중 최단 거리를 가진 정점 선택
- 그 정점을 기준으로 인접한 정점들의 거리를 갱신
- if dist[u] + weight(u,v) < dist[v]: dist[v] = dist[u] + weight(u,v)
- 모든 정점을 방문할 때까지 반복
단계별 동작 예시
예시 그래프)
A -(4)- B
| |
(2) (1)
| |
C -(5)- D
- A 시작 → 거리: A(0), B(4), C(2), D(∞)
- 가장 짧은 C(2) 선택 → D 거리 = 2+5=7
- B(4) 선택 → D 거리 = min(7, 4+1)=5
- 모든 정점 방문 완료 → 결과: D까지 5
코드)
void Dijkstra(vector<pair<int,int>> adj[], int start, int V) {
vector<int> dist(V, INF);
priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
dist[start] = 0;
pq.push({0, start});
while (!pq.empty()) {
int cost = pq.top().first;
int u = pq.top().second;
pq.pop();
if (cost > dist[u]) continue;
for (auto [v, w] : adj[u]) {
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
pq.push({dist[v], v});
}
}
}
for (int i = 0; i < V; i++)
printf("dist[%d] = %d\n", i, dist[i]);
}
(3) Bellman-Ford Algorithm (벨만-포드 알고리즘)
음수 가중치가 존재하는 그래프에서도 동작하는 알고리즘.
모든 간선을 V-1번 반복 검사하며 더 짧은 경로가 있으면 계속 갱신함.
== “한 간선을 여러 번 완화(relaxation)하면서 최단 거리를 점진적으로 계산한다.”
== “모든 간선을 (V-1)번 반복해서 검사하며 더 짧은 경로가 있다면 계속 갱신한다.”
다익스트라보다 느리지만, 음수 가중치가 있어도 작동함.
- 음수 가중치 허용 (단, 음수 사이클 불)
- 시간 복잡도: O(VE)
- 단순하고 확실하지만 느려서 큰 그래프엔 부적합함.
Bellman–Ford 알고리즘 :: 바바썬 <- 자세한 내용은 과거 정리 내용 참고
처리과정
1. 시작 정점 거리 = 0, 나머지는 ∞
2. 모든 간선을 (V-1)번 반복 검사 (모든 간선 (u, v)에 대해)
if (dist[u] + w < dist[v])
dist[v] = dist[u] + w
3. 한 번 더 검사해서 값이 바뀌면 → 음수 사이클 존재
코드)
void BellmanFord(int n, int v) {
for (int i = 0; i < n; i++)
dist[i] = length[v][i];
for (int k = 2; k <= n - 1; k++)
for (each edge (i, u))
if (dist[u] > dist[i] + length[i][u])
dist[u] = dist[i] + length[i][u];
}
2. All Pair Shortest Path
(1) Floyd–Warshall Algorithm (플로이드–워셜 알고리즘)
모든 정점 쌍 (i, j)에 대해 k번째 정점을 중간 경유지로 거칠 때의 최소 비용을 반복적으로 갱신함.
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
== “정점 i에서 j로 가는 경로 중, k를 거치는 것이 더 짧은가?”를 반복 검사.
Floyd–Warshall 알고리즘 :: 바바썬 <- 자세한 내용은 과거 정리 내용 참고
처리과정
- dist[i][j]를 초기화
- i == j → 0
- 간선이 있으면 그 가중치
- 없으면 INF
- 모든 정점 k에 대해 반복:
- for i in V: for j in V: if dist[i][k] + dist[k][j] < dist[i][j]: dist[i][j] = dist[i][k] + dist[k][j]
단계별 동작 예시
예시 그래프)
A → B (4)
A → C (11)
B → C (2)
C → D (1)
dist[A][D] 의 경우
| A 0 | A에서D로 바로 이동 | 불가능 | ∞ | |
| A 1 | 정점 하나 거쳐서 D로 이동 | A → C → D | 11 + 1 = 12 | A 0 과 비교 후 12 선택 |
| A 2 | 정점 두개 거쳐서 D로 이동 | A → B → C → D | 4 + 2 + 1 = 7 | A 1과 비교 후 7 선책 |
==> 최종 dist[A][D] = 7
코드)
void FloydWarshall(int dist[][N], int V) {
for (int k = 0; k < V; k++)
for (int i = 0; i < V; i++)
for (int j = 0; j < V; j++)
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
정리하자면,
| 알고리즘 | 적용 | 음수 가중치 | 시간복잡도 | 특징 |
| BFS | 비가중치 그래프 | X | O(V+E) | 단순하고 빠름 |
| Dijkstra | 양수 가중치 그래프 | X | O(E log V) | 효율적, Heap 사용 |
| Bellman–Ford | 음수 가중치 포함 | O (음수 사이클 X) | O(VE) | 느리지만 확실 |
| Floyd–Warshall | 모든 정점 쌍 | O (음수 사이클 X) | O(V³) | 전체 경로 계산 |
'이론공부 > 자료구조, 알고리즘' 카테고리의 다른 글
| 7. Sorting (2) (0) | 2025.11.12 |
|---|---|
| 7. Sorting (1) (0) | 2025.11.11 |
| 6. Graph (2) (0) | 2025.11.10 |
| 6. Graph (1) (0) | 2025.11.10 |
| 5. Tree (3) - Types of Binary Trees (1) | 2025.11.09 |