사용 개념: 다익스트라(배열 판), 벨만–포드 알고리즘, 플로이드 알고리즘의 경로 출력.
세 알고리즘의 손 계산은 같은 하위목표로 이루어진다. ① 처음 표 쓰기 ② 한 단계 고치기(무엇을 기준으로 어느 칸을 고치는지가 알고리즘마다 다르다) ③ 멈춤 확인 ④ 적어 둔 표로 길 읽기. 표는 길이를 적는 표와 길을 되짚을 표, 둘을 함께 채운다1.
| ② 한 단계 | ④ 길을 되짚을 표 | |
|---|---|---|
| 다익스트라 | 아직 안 고른 점 가운데 \(d\)가 가장 작은 점을 고르고, 그 점에서 나가는 간선으로 고친다 | \(p[v]\) = \(v\) 바로 앞의 점. 도착점에서 거꾸로 따라간다 |
| 벨만–포드 | 윗줄의 값만 읽어 모든 간선으로 한 줄을 만든다 | \(p(v, k)\). 마지막 줄을 거꾸로 따라간다 |
| 플로이드 | 거쳐 가도 되는 점 \(k\)를 하나 늘려 모든 칸을 고친다 | \(kay(i, j)\) = 가운데의 한 점. 길을 둘로 가른다 |
−는 “아직 길이 없다(무한대)”는 뜻이다.
문제 1 · 완전한 풀이
점 1 ~ 7, 방향 간선과 비용이 다음과 같다. 1에서 모든 점까지 가장 짧은 길이를 다익스트라의 방법으로 구한다. \(d\)와 \(p\)는 배열로 두고, 고를 점은 배열을 훑어 찾는다.
1→3: 2 1→2: 6 1→4: 16 1→7: 14 3→2: 7 3→5: 3 3→6: 8
2→4: 5 2→5: 4 5→4: 4 5→7: 10 4→7: 3 6→7: 1
- 처음 표: \(d[1] = 0\)이고 나머지는 −다.
- 한 단계: 아직 안 고른 점 가운데 \(d\)가 가장 작은 점을 고른다. 그 점에서 나가는 간선 \((u, v)\)마다 \(d[u] + \text{비용}\)이 \(d[v]\)보다 작으면 \(d[v]\)를 고치고 \(p[v] = u\)로 적는다.
| 고른 점 | \(d[1]\) ~ \(d[7]\) | \(p[1]\) ~ \(p[7]\) | 이 단계에서 고친 것 |
|---|---|---|---|
| 1 | 0, 6, 2, 16, −, −, 14 | −, 1, 1, 1, −, −, 1 | 2, 3, 4, 7 |
| 3 | 0, 6, 2, 16, 5, 10, 14 | −, 1, 1, 1, 3, 3, 1 | 5(2 + 3), 6(2 + 8). 2는 2 + 7 = 9가 6보다 커서 그대로 |
| 5 | 0, 6, 2, 9, 5, 10, 14 | −, 1, 1, 5, 3, 3, 1 | 4(5 + 4). 7은 5 + 10 = 15가 14보다 커서 그대로 |
| 2 | 0, 6, 2, 9, 5, 10, 14 | −, 1, 1, 5, 3, 3, 1 | 없음. 4는 6 + 5 = 11이 9보다 크다 |
| 4 | 0, 6, 2, 9, 5, 10, 12 | −, 1, 1, 5, 3, 3, 4 | 7(9 + 3) |
| 6 | 0, 6, 2, 9, 5, 10, 11 | −, 1, 1, 5, 3, 3, 6 | 7(10 + 1) |
| 7 | 0, 6, 2, 9, 5, 10, 11 | −, 1, 1, 5, 3, 3, 6 | 없음 |
- 멈춤 확인: 일곱 점을 모두 골랐다. 고른 순서는 1, 3, 5, 2, 4, 6, 7이고 길이가 짧은 순서(0, 2, 5, 6, 9, 10, 11)다.
- 길 읽기: 7로 가는 길은 \(p[7] = 6\), \(p[6] = 3\), \(p[3] = 1\)을 거꾸로 이어 1 → 3 → 6 → 7이고 길이는 \(2 + 8 + 1 = 11\)이다. 4로 가는 길은 \(p[4] = 5\), \(p[5] = 3\)이라 1 → 3 → 5 → 4, 길이 9다.
7의 값은 14 → 12 → 11로 세 번 바뀌었다. “가장 싼 간선만 따라가기”로는 1 → 3 → 5 → 4 → 7(길이 12)을 얻어 틀린다.
문제 2 · 마지막 하위목표만 빈칸
점 1 ~ 6, 방향 간선과 비용이 다음과 같다. 6→2의 비용이 음수라 벨만–포드를 쓴다. 출발점은 1이다.
1→2: 3 1→4: 7 2→3: 4 2→4: 5 3→5: 3 3→6: 6 4→5: 9 4→6: 1 6→2: −6
- 처음 표: \(d(1, 0) = 0\)이고 나머지는 −다.
- 한 단계: \(d(v, k) = \min\{d(v, k-1),\ d(w, k-1) + \text{비용}(w, v)\}\). 윗줄의 값만 읽는다.
| \(k\) | \(d(1,k)\) ~ \(d(6,k)\) | \(p(1,k)\) ~ \(p(6,k)\) |
|---|---|---|
| 0 | 0, −, −, −, −, − | −, −, −, −, −, − |
| 1 | 0, 3, −, 7, −, − | −, 1, −, 1, −, − |
| 2 | 0, 3, 7, 7, 16, 8 | −, 1, 2, 1, 4, 4 |
| 3 | 0, 2, 7, 7, 10, 8 | −, 6, 2, 1, 3, 4 |
| 4 | 0, 2, 6, 7, 10, 8 | −, 6, 2, 1, 3, 4 |
| 5 | 0, 2, 6, 7, 9, 8 | −, 6, 2, 1, 3, 4 |
- 멈춤 확인: 점이 6개라 \(k = 5\)까지 채운다. \(k = 5\) 줄도 윗줄과 달라 일찍 멈추지 못한다.
- 길 읽기: 마지막 줄의 \(p\)로 5, 6, 3으로 가는 가장 짧은 길과 길이를 쓰라. __
답
- 5: \(p = 3\), 3의 \(p = 2\), 2의 \(p = 6\), 6의 \(p = 4\), 4의 \(p = 1\). 거꾸로 이으면 1 → 4 → 6 → 2 → 3 → 5, 길이 \(7 + 1 - 6 + 4 + 3 = 9\).
- 6: 1 → 4 → 6, 길이 \(7 + 1 = 8\).
- 3: 1 → 4 → 6 → 2 → 3, 길이 \(7 + 1 - 6 + 4 = 6\).
5로 가는 길은 간선이 5개(\(n - 1\)개)다. 그래서 \(d(5, k)\)가 \(k = 5\)에서야 9가 된다.
문제 3 · 하위목표 절반이 빈칸
점 8개인 그래프에 플로이드의 방법을 끝까지 돌려 얻은 \(kay\) 표가 다음과 같다. \(kay(i, j)\)는 \(i\)에서 \(j\)로 가는 가장 짧은 길 위에서 번호가 가장 큰 중간 점이고, 0이면 간선 하나로 간다.
| \(kay\) | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 4 | 0 | 0 | 4 | 8 | 8 | 5 |
| 2 | 8 | 0 | 8 | 5 | 0 | 8 | 8 | 5 |
| 3 | 7 | 0 | 0 | 5 | 0 | 0 | 6 | 5 |
| 4 | 8 | 0 | 8 | 0 | 2 | 8 | 8 | 5 |
| 5 | 8 | 4 | 8 | 0 | 0 | 8 | 8 | 0 |
| 6 | 7 | 7 | 7 | 7 | 7 | 0 | 0 | 7 |
| 7 | 0 | 4 | 1 | 1 | 4 | 8 | 0 | 0 |
| 8 | 7 | 7 | 7 | 7 | 7 | 0 | 6 | 0 |
4에서 3으로 가는 가장 짧은 길을 되짚는다. 필요한 간선의 비용은 4→2: 5, 2→5: 4, 5→8: 1, 8→6: 2, 6→7: 1, 7→1: 2, 1→3: 5다.
- 첫 갈림: \(kay(4, 3) = 8\). (4, 8)과 (8, 3)으로 가른다.
- (4, 8) 토막: __
- (8, 3) 토막: \(kay(8, 3) = 7\)이라 (8, 7)과 (7, 3)으로 가른다. \(kay(8, 7) = 6\)이고 (8, 6), (6, 7)은 0이다. \(kay(7, 3) = 1\)이고 (7, 1), (1, 3)은 0이다. 이 토막은 8 → 6 → 7 → 1 → 3이다.
- 길과 길이: __
답
- \(kay(4, 8) = 5\)라 (4, 5)와 (5, 8)로 가른다. \(kay(4, 5) = 2\)이고 (4, 2), (2, 5)는 0이다. \(kay(5, 8) = 0\)이다. 이 토막은 4 → 2 → 5 → 8이다.
- 길은 4 → 2 → 5 → 8 → 6 → 7 → 1 → 3이고 길이는 \(5 + 4 + 1 + 2 + 1 + 2 + 5 = 20\)이다. 가를 때마다 토막의 “가장 큰 중간 점”이 8 → 5와 7 → 2, 6, 1 → 0으로 줄어든다.
문제 4 · 독립 문제
점 1 ~ 5, 방향 간선과 비용이 다음과 같다. 출발점은 1이다.
1→2: 2 1→3: 5 3→2: −4 2→4: 3 4→5: 1 3→5: 6
(가) 문제 1의 방법(다익스트라, 고른 점은 다시 고치지 않는다, \(d\)가 같으면 번호가 작은 점을 먼저)으로 \(d\)를 구하라. (나) 벨만–포드의 \(d(v, k)\) 표를 \(k = 0\)부터 4까지 채우고 마지막 줄의 \(p\)를 쓰라. (다) 5로 가는 가장 짧은 길을 쓰고, (가)가 틀린 점을 모두 들어라. 왜 틀렸는가?
답
(가) 고르는 순서 1, 2, 3, 4, 5. 1을 고르면 \(d\) = 0, 2, 5, −, −. 2를 고르면 \(d[4] = 5\). 3을 고르면(3과 4가 5로 같아 번호가 작은 3) 3→2로 \(5 - 4 = 1\)이 나오지만 2는 이미 골라서 고치지 않고, \(d[5] = 11\). 4를 고르면 \(d[5] = 6\). 결과는 0, 2, 5, 5, 6이다.
(나)
| \(k\) | \(d(1,k)\) ~ \(d(5,k)\) |
|---|---|
| 0 | 0, −, −, −, − |
| 1 | 0, 2, 5, −, − |
| 2 | 0, 1, 5, 5, 11 |
| 3 | 0, 1, 5, 4, 6 |
| 4 | 0, 1, 5, 4, 5 |
\(k = 2\) 줄의 \(d(4, 2) = 5\)는 윗줄의 \(d(2, 1) = 2\)에 3을 더한 것이다. 같은 줄의 1을 쓰면 안 된다. 마지막 줄의 \(p\)는 −, 3, 1, 2, 4다.
(다) \(p\)를 거꾸로 따라가면 5 ← 4 ← 2 ← 3 ← 1이라 길은 1 → 3 → 2 → 4 → 5, 길이 \(5 - 4 + 3 + 1 = 5\)다. (가)는 2, 4, 5를 틀렸다(2, 5, 6이라 했지만 맞는 값은 1, 4, 5). 다익스트라는 가장 가까운 2를 거리 2로 확정했는데, 더 먼 3을 거쳐 음수 간선을 타면 1로 준다. 2가 틀리니 2를 거쳐 가는 4와 5도 따라 틀린다. 벨만–포드의 네 줄은 모두 윗줄과 달라서 끝까지 채워야 한다.
-
모든 답은 문제 코드로 확인했다. ↩