[Algorithm] Shortest Path
๐ฃ
๋ณธ ํฌ์คํธ๋ โ์ด๊ฒ์ด ์ทจ์
์ ์ํ ์ฝ๋ฉ ํ
์คํธ๋ค with ํ์ด์ฌโ์ ๊ณต๋ถํ๊ณ ์์ฑํ์์ต๋๋ค :)
click > (์ด์ฝํ
2021) ์ด๊ฒ์ด ์ทจ์
์ ์ํ ์ฝ๋ฉ ํ
์คํธ๋ค with ํ์ด์ฌ
Shortest Path
์ด๋ก
์ต๋จ ๊ฒฝ๋ก(Shortest Path) ์๊ณ ๋ฆฌ์ฆ์ ํน์ ์ง์ ๊น์ง ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋๋ฌํ๋ ๋ฐฉ๋ฒ์ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ ์ ํ์๋ ๋ค์ํ ์ข ๋ฅ๊ฐ ์๋๋ฐ ์ํฉ์ ๋ง๋ ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ด ์ด๋ฏธ ์ ๋ฆฝ๋์ด ์๋ค.
์ต๋จ ๊ฒฝ๋ก ๋ฌธ์ ๋ ๋ณดํต ๊ทธ๋ํ๋ฅผ ์ด์ฉํด ๊ฐ ์ง์ ์ ๋ ธ๋๋ก, ์ง์ ๊ฐ ์ฐ๊ฒฐ๋ ๋๋ก๋ ๊ฐ์ ์ผ๋ก ํํ๋๋ค. โก๏ธ ๊ทธ๋ํ์ ํํ ๋ฐฉ์
์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ๋ ํฌ๊ฒ 3์ข ๋ฅ๊ฐ ์๋ค.
- ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ : ํ ์ง์ ์์ ๋ค๋ฅธ ํน์ ์ง์ ๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๊ตฌํด์ผ ํ๋ ๊ฒฝ์ฐ
- ํ๋ก์ด๋ ์์ ์๊ณ ๋ฆฌ์ฆ : ๋ชจ๋ ์ง์ ์์ ๋ค๋ฅธ ๋ชจ๋ ์ง์ ๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๋ชจ๋ ๊ตฌํด์ผ ํ๋ ๊ฒฝ์ฐ
- ๋ฒจ๋ง ํฌ๋ ์๊ณ ๋ฆฌ์ฆ : ๊ฐ์ ์ ๊ฐ์ค์น๊ฐ ์์์ผ ๋, ํ ๋ ธ๋์์ ๋ค๋ฅธ ๋ ธ๋๊น์ง์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ
๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ
๋ค์ต์คํธ๋ผ ์ต๋จ ๊ฒฝ๋ก ์๊ณ ๋ฆฌ์ฆ์ ๊ทธ๋ํ์์ ์ฌ๋ฌ ๊ฐ์ ๋ ธ๋๊ฐ ์์ ๋, ํน์ ํ ๋ ธ๋์์ ์ถ๋ฐํ์ฌ ๋ค๋ฅธ ๋ ธ๋๋ก ๊ฐ๋ ๊ฐ๊ฐ์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๊ตฌํด์ฃผ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ๋งค๋ฒ ๊ฐ์ฅ ๋น์ฉ์ด ์ ์ ๋ ธ๋๋ฅผ ์ ํํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ถ๋ฅ๋๋ค. ์๊ณ ๋ฆฌ์ฆ์ ์๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ๋ค.
1๏ธโฃ ์ถ๋ฐ ๋ ธ๋๋ฅผ ์ค์ ํ๋ค.
2๏ธโฃ ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ์ด๊ธฐํํ๋ค.
3๏ธโฃ ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋ ์ค์์ ์ต๋จ ๊ฑฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ์งง์ ๋ ธ๋๋ฅผ ์ ํํ๋ค.
4๏ธโฃ ํด๋น ๋ ธ๋๋ฅผ ๊ฑฐ์ณ ๋ค๋ฅธ ๋ ธ๋๋ก ๊ฐ๋ ๋น์ฉ์ ๊ณ์ฐํ์ฌ ์ต๋จ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ๊ฐฑ์ ํ๋ค
5๏ธโฃ 3-4๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
๊ตฌํ ์ฝ๋
def dijkstra(start, distance, graph):
q = []
heapq.heappush(q,(0,start))
distance[start] = 0
while q:
dist, node = heapq.heappop(q)
if distance[node] < dist: # ์ด๋ฏธ ์ฒ๋ฆฌํ ์ ์๋ ๋
ธ๋๋ผ๋ฉด ๋ฌด์
continue
for i in graph[node]: # ํ์ฌ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๋
ธ๋๋ค ํ์ธ
cost = dist+i[1] # ๊ฑฐ๋ฆฌ ๊ณ์ฐ
if cost < distance[i[0]]: # ํ์ฌ ์ต๋จ๊ฑฐ๋ฆฌ๋ณด๋ค ์๋ค๋ฉด ๊ฐฑ์ ํ๊ณ ํ์ push
distance[i[0]] = cost
heapq.heappush(q,(cost, i[0]))
์๊ฐ ๋ณต์ก๋
- ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ๋ฆฌ์คํธ๋ก ๊ตฌํํ์ ๋ โ $O(V^2)$
- ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ์ฐ์ ์์ ํ(heap)์ผ๋ก ๊ตฌํํ์ ๋ โ $O(E*logV)$
ํ๋ก์ด๋ ์์ ์๊ณ ๋ฆฌ์ฆ
ํ๋ก์ด๋ ์์ ์๊ณ ๋ฆฌ์ฆ์ ๋ชจ๋ ์ง์ ์์ ๋ค๋ฅธ ๋ชจ๋ ์ง์ ๊น์ง์ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ๋ชจ๋ ๊ตฌํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ฌ์ฉํ ์ ์๋ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ ํ์์ ๋ง๊ฒ ๋์ํ๊ธฐ ๋๋ฌธ์ ๋ค์ด๋๋ฏน ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ๋ณผ ์ ์๋ค.
๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ๋จ๊ณ๋ง๋ค ๋ฐฉ๋ฌธํ์ง ์์ ๋ ธ๋ ์ค์์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐ์ง๋ ๋ ธ๋๋ฅผ ํ๋์ฉ ์ ํํ๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋น ๋ ธ๋๋ฅผ ๊ฑฐ์ณ ๊ฐ๋ ๊ฒฝ๋ก๋ฅผ ํ์ธํ๋ฉฐ ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ(1์ฐจ์ ๋ฆฌ์คํธ)๋ฅผ ๊ฐฑ์ ํ๋ ๋ฐฉ์์ด๋ค.
ํ๋ก์ด๋ ์์ ์๊ณ ๋ฆฌ์ฆ์ ๋จ๊ณ๋ง๋ค ํ์ฌ ๋ ธ๋๋ฅผ ๊ฑฐ์ณ ๊ฐ๋ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ๊ณ ๋ คํ๋ค. ๋ชจ๋ ๋ ธ๋์ ๋ํ์ฌ ๋ค๋ฅธ ๋ชจ๋ ๋ ธ๋๋ก ๊ฐ๋ ์ต๋จ ๊ฑฐ๋ฆฌ ์ ๋ณด๋ฅผ ๋ชจ๋ ๋ด์์ผ ํ๊ธฐ ๋๋ฌธ์ 2์ฐจ์์ ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ๋ก ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ค. ์๊ณ ๋ฆฌ์ฆ์ ์๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ๋ค.
1๏ธโฃ ํ์ฌ ํ์ธํ๊ณ ์๋ ๋ ธ๋๋ฅผ ์ ์ธํ๊ณ , N-1๊ฐ์ ๋ ธ๋ ์ค์์ ์๋ก ๋ค๋ฅธ ๋ ธ๋ (A, B) ์์ ์ ํํ๋ค.
2๏ธโฃ A โ ํ์ฌ ๋ ธ๋ โ B๋ก ๊ฐ๋ ๋น์ฉ์ ํ์ธํ๊ณ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ๋ค.
๊ฐ ๋จ๊ณ์์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์ ํ๋ ์ ํ์์ $D_{ab} = min(D_{ab}, D_{ak}+D_{kb})$ ์ด๋ค.
๊ตฌํ ์ฝ๋
for k in range(1,n+1):
for i in range(1,n+1):
for j in range(1,n+1):
graph[i][j] = min(graph[i][j], graph[i][k]+graph[k][j])
์๊ฐ ๋ณต์ก๋
N๊ฐ์ ๋ ธ๋์ ๋ํด์ $_{n-1}P_2$๊ฐ์ ์์ ๋ฐ๋ณตํด์ ํ์ธํ๋ฉด ๋๋ฏ๋ก $O(N^3)$์ด๋ผ๊ณ ํ ์ ์๋ค.
๋ฒจ๋ง ํฌ๋ ์๊ณ ๋ฆฌ์ฆ
๋ฒจ๋ง ํฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋๊ฐ์ด ํ ๋ ธ๋์์ ๋ค๋ฅธ ๋ ธ๋๊น์ง ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค. ์ฐจ์ด์ ์ ๋ฒจ๋ง ํฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ์ ์ ๊ฐ์ค์น๊ฐ ์์์ผ ๋๋ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํ ์ ์๋ค๋ ์ ์ด๋ค. ์๊ณ ๋ฆฌ์ฆ์ ์๋ฆฌ๋ ๋ค์๊ณผ ๊ฐ๋ค.
1๏ธโฃ ์ถ๋ฐ ๋ ธ๋๋ฅผ ์ค์ ํ๋ค.
2๏ธโฃ ์ต๋จ ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ์ด๊ธฐํํ๋ค.
3๏ธโฃ ๋ชจ๋ ๊ฐ์ E๊ฐ๋ฅผ ํ๋์ฉ ํ์ธํ๋ค.
4๏ธโฃ ํด๋น ๋ ธ๋๋ฅผ ๊ฑฐ์ณ ๋ค๋ฅธ ๋ ธ๋๋ก ๊ฐ๋ ๋น์ฉ์ ๊ณ์ฐํ์ฌ ์ต๋จ๊ฑฐ๋ฆฌ ํ ์ด๋ธ์ ๊ฐฑ์ ํ๋ค
5๏ธโฃ 3-4๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
โ
์์ ๊ฐ์ ์ํ(cycle) ๋ฐ์์ ํ์ธ!
4๏ธโฃ๋ฒ ๊ณผ์ ์ ํ ๋ฒ ๋ ์ํํ๊ณ ์ด๋ ์ต๋จ ๊ฑฐ๋ฆฌ ํ
์ด๋ธ์ด ๊ฐฑ์ ๋๋์ง๋ฅผ ํ์ธํ๋ค. ๊ฐฑ์ ๋๋ ๊ฒฝ์ฐ ์์ ๊ฐ์ ์ํ์ด ์กด์ฌํ๋ค๋ ๊ฒ์ด๋ค.
์์ ๊ฐ์ ์ํ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ๋น์ฉ์ ๋ฌดํํ ์ค์ผ ์ ์๊ธฐ ๋๋ฌธ์ ์ต๋จ ๊ฑฐ๋ฆฌ๋ฅผ ์ํ ์ ์๊ฒ ๋๋ฏ๋ก ๊ผญ ํ์ธํด์ผ ํ๋ค.
๊ตฌํ ์ฝ๋
def bellmanFord(start):
distance[start] = 0
for i in range(v): # ์ ์ฒด v - 1๋ฒ ๋ฐ๋ณต
for j in range(e): # ๋งค ๋ฐ๋ณต๋ง๋ค '๋ชจ๋ ๊ฐ์ '์ ํ์ธํ๋ค.
cur_node = edges[j][0]
next_node = edges[j][1]
edge_cost = edges[j][2]
# ํ์ฌ ๊ฐ์ ์ ๊ฑฐ์ณ์ ๋ค๋ฅธ ๋
ธ๋๋ก ์ด๋ํ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋ ์งง์ ๊ฒฝ์ฐ
if distance[cur_node] != INF and distance[next_node] > distance[cur_node] + edge_cost:
distance[next_node] = distance[cur_node] + edge_cost
# v๋ฒ์งธ ๋ผ์ด๋์์๋ ๊ฐ์ด ๊ฐฑ์ ๋๋ค๋ฉด ์์ ์ํ์ด ์กด์ฌ
if i == v - 1:
return True
return False
REF : https://deep-learning-study.tistory.com/587
์๊ฐ ๋ณต์ก๋
๋ชจ๋ ๋ ธ๋์์ ๋ชจ๋ ๊ฐ์ ์ ํ์ธํ๋ฏ๋ก O(VE)์ด๋ค.
์ค์ ๋ฌธ์
[์ค์ ๋ฌธ์ 1] ๋ฏธ๋๋์
INF = int(1e9)
n, m = map(int, input().split())
graph = [[INF] * (n+1) for _ in range(n+1)]
for a in range(1,n+1):
for b in range(1,n+1):
if a == b:
graph[a][b] = 0 # ์๊ธฐ ์์ ๋น์ฉ์ 0์ผ๋ก ์ด๊ธฐํ
for _ in range(m):
a, b = map(int, input().split())
graph[a][b] = 1
graph[b][a] = 1
x, k = map(int, input().split())
for k in range(1, n+1):
for i in range(1, n+1):
for j in range(1, n+1):
graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
distance = graph[1][k] + graph[k][x]
if distance >= INF:
print(-1)
else:
print(distance)
[์ค์ ๋ฌธ์ 2] ์ ๋ณด
import heapq
import sys
input = sys.stdin.readline
INF = int(1e9) # ๋ฌดํ์ ์๋ฏธํ๋ ๊ฐ์ผ๋ก 10์ต์ ์ค์
# ๋
ธ๋์ ๊ฐ์, ๊ฐ์ ์ ๊ฐ์, ์์ ๋
ธ๋๋ฅผ ์
๋ ฅ๋ฐ๊ธฐ
n, m, start = map(int, input().split())
# ๊ฐ ๋
ธ๋์ ์ฐ๊ฒฐ๋์ด ์๋ ๋
ธ๋์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๋ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค๊ธฐ
graph = [[] for i in range(n + 1)]
# ์ต๋จ ๊ฑฐ๋ฆฌ ํ
์ด๋ธ์ ๋ชจ๋ ๋ฌดํ์ผ๋ก ์ด๊ธฐํ
distance = [INF] * (n + 1)
# ๋ชจ๋ ๊ฐ์ ์ ๋ณด๋ฅผ ์
๋ ฅ๋ฐ๊ธฐ
for _ in range(m):
x, y, z = map(int, input().split())
# X๋ฒ ๋
ธ๋์์ Y๋ฒ ๋
ธ๋๋ก ๊ฐ๋ ๋น์ฉ์ด Z๋ผ๋ ์๋ฏธ
graph[x].append((y, z))
def dijkstra(start):
q = []
# ์์ ๋
ธ๋๋ก ๊ฐ๊ธฐ ์ํ ์ต๋จ ๊ฒฝ๋ก๋ 0์ผ๋ก ์ค์ ํ์ฌ, ํ์ ์ฝ์
heapq.heappush(q, (0, start))
distance[start] = 0
while q: # ํ๊ฐ ๋น์ด์์ง ์๋ค๋ฉด
# ๊ฐ์ฅ ์ต๋จ ๊ฑฐ๋ฆฌ๊ฐ ์งง์ ๋
ธ๋์ ๋ํ ์ ๋ณด๋ฅผ ๊บผ๋ด๊ธฐ
dist, now = heapq.heappop(q)
if distance[now] < dist:
continue
# ํ์ฌ ๋
ธ๋์ ์ฐ๊ฒฐ๋ ๋ค๋ฅธ ์ธ์ ํ ๋
ธ๋๋ค์ ํ์ธ
for i in graph[now]:
cost = dist + i[1]
# ํ์ฌ ๋
ธ๋๋ฅผ ๊ฑฐ์ณ์, ๋ค๋ฅธ ๋
ธ๋๋ก ์ด๋ํ๋ ๊ฑฐ๋ฆฌ๊ฐ ๋ ์งง์ ๊ฒฝ์ฐ
if cost < distance[i[0]]:
distance[i[0]] = cost
heapq.heappush(q, (cost, i[0]))
# ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ์ํ
dijkstra(start)
# ๋๋ฌํ ์ ์๋ ๋
ธ๋์ ๊ฐ์
count = 0
# ๋๋ฌํ ์ ์๋ ๋
ธ๋ ์ค์์, ๊ฐ์ฅ ๋ฉ๋ฆฌ ์๋ ๋
ธ๋์์ ์ต๋จ ๊ฑฐ๋ฆฌ
max_distance = 0
for d in distance:
# ๋๋ฌํ ์ ์๋ ๋
ธ๋์ธ ๊ฒฝ์ฐ
if d != 1e9:
count += 1
max_distance = max(max_distance, d)
# ์์ ๋
ธ๋๋ ์ ์ธํด์ผ ํ๋ฏ๋ก count - 1์ ์ถ๋ ฅ
print(count - 1, max_distance)
๋๊ธ๋จ๊ธฐ๊ธฐ