๋ฐ˜์‘ํ˜•

 

๊ตญ๋ฏผ๋Œ€ํ•™๊ต์—์„œ "์‰ฝ๊ฒŒ ๋ฐฐ์šฐ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜" ๊ต์žฌ๋ฅผ ์ด์šฉํ•œ
 ๋ฐ•ํ•˜๋ช… ๊ต์ˆ˜๋‹˜์˜ ๊ฐ•์˜ ๊ต์•ˆ์„ ์ด์šฉํ•˜์—ฌ ์ˆ˜์—… ๋‚ด์šฉ์„ ์ •๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค

 

 

Shortest Paths

 

s์—์„œ e๋กœ ๊ฐ€๋Š” ๊ฒฝ๋กœ๋“ค ์ค‘์—์„œ๋Š” s -> b -> c -> e ์˜ ๋น„์šฉ์ด 12๋กœ ์ ค ์ ์Œ

 

 

Shortest Paths๋ž€ ๋ง ๊ทธ๋Œ€๋กœ ๋‘ ์  ์‚ฌ์ด์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ์ž„

 

=> ๋‘ ์  ์‚ฌ์ด์˜ ๊ฒฝ๋กœ ์ค‘ ๋น„์šฉ์ด ์ตœ์†Œ์ธ ๊ฒฝ๋กœ


(๊ฒฝ๋กœ ๋‚ด ๊ฐ„์„ ๋“ค์˜ ๋น„์šฉ ํ•ฉ)

 

Single Source Shortest Paths

 

๊ทธ๋Ÿผ ์ด๋ฒˆ ํฌ์ŠคํŒ…์˜ ์ฃผ์ œ์ธ Single Source Shortest Paths๋Š” ๋ญ˜๊นŒ?

 

์ด๋Š” ํ•œ ์ ๊ณผ ๋‹ค๋ฅธ ๋ชจ๋“  ์  ์‚ฌ์ด์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์˜๋ฏธํ•จ

 

 

=> ์‹œ์ž‘ ์ •์  (source node) s์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ ๊นŒ์ง€์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ ์ฐพ๊ธฐ๊ฐ€ ๊ณง, s๊ฐ€ root์ธ shortest-path tree ์ฐพ๊ธฐ์ž„

(์ผ์ข…์˜ spanning tree๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Œ)

 

Dijkstra's Algorithm

 

๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ Single Source Shortest Path๋ฅผ ๋ชจ๋‘ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž„

๋‹จ, ๋ชจ๋“  ๊ฐ„์„ ์˜ weight๊ฐ€ 0 ์ด์ƒ์˜ ๊ฐ’์„ ๊ฐ€์ง

(= ์Œ์ˆ˜ ๋ถˆ๊ฐ€)

 

 

 

๋ฐฉ์‹์€ Prim ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์œ ์‚ฌํ•œ๋ฐ, ์ •์  ์ง‘ํ•ฉ S๋ฅผ ์ ์ง„์ ์œผ๋กœ ํ™•์žฅํ•ด๋‚˜๊ฐ€๋Š” ๋ฐฉ์‹์ž„

 

1. ์‹œ์ž‘ ์ •์  s๋งŒ ํฌํ•จํ•˜๋Š” ์ง‘ํ•ฉ S={s}๋ฅผ ์ƒ์„ฑ

 

2. S์— ํฌํ•จ๋˜์ง€ ์•Š์€ ์ •์  ์ค‘ s์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์  v๋ฅผ ์ฐพ์•„ S์— ํŽธ์ž…

 

=> v์˜ ์ด์ „ ๋…ธ๋“œ ์ €์žฅ (๊ฒฝ๋กœ ์ฐพ์„ ๋•Œ ํ™œ์šฉ)

 

์ด์ œ 2๋ฒˆ ๊ณผ์ •์„ ๋ชจ๋“  ์ •์ ์ด S์— ํฌํ•จ๋  ๋•Œ ๊นŒ์ง€ ๋ฐ˜๋ณตํ•˜๋ฉด๋จ

 

Prim ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ์˜ ์ฐจ์ด์ ์€ 

Prim์€ ์ง‘ํ•ฉ S๊นŒ์ง€์˜ ๊ฐ„์„  ํ•˜๋‚˜๋งŒ ํ™•์ธํ•˜๋Š” ๋ฐ˜๋ฉด ๋‹ค์ต์ŠคํŠธ๋ผ๋Š” ์‹œ์ž‘ ์ •์  s๊นŒ์ง€์˜ ์ด ๊ฑฐ๋ฆฌ๋กœ ๋น„๊ตํ•จ

 

 

pseudo ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด

 

# s : ์‹œ์ž‘ ์ •์ , n : ์ •์  ์ˆ˜

prev = [-1] * n  # ์ด์ „ ์ •์ 
d = [โˆž] * n  # s์™€์˜ ๊ฑฐ๋ฆฌ
d[s] = 0  # ์‹œ์ž‘ ์ •์ ์ธ s๋ฅผ 0์œผ๋กœ ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋ฅผ โˆž๋กœ ์ดˆ๊ธฐํ™” ํ•˜๋ฉด๋จ
S = set()

Q = min_heap()
Q.enqueue((0, s))  # ์ˆœ์„œ๋Œ€๋กœ ๊ฐ€์ค‘์น˜, node๋ฅผ ์˜๋ฏธ

while Q is not empty :
	w, u = Q.dequeue()
    
    if u in S : continue
    S.add(u)
    
    for v, w_uv in neighbors(u) :
    	if v not in S and d[u] + w_uv < d[v] :
        	d[v] = d[u] + w_uv
            prev[v] = u
            Q.enqueue((d[v], v))

 

 

๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ์›๋ฆฌ

 

 

 

์ตœ๋‹จ ๊ฒฝ๋กœ์˜ ๋ถ€๋ถ„ ๊ฒฝ๋กœ ์—ญ์‹œ ์ตœ๋‹จ ๊ฒฝ๋กœ์ž„์„ ์ด์šฉํ•จ

 

P๊ฐ€ s์™€ e ์‚ฌ์ด์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ผ๋ฉด,

 

s์™€ ๊ฒฝ๋กœ์ƒ์˜ ์ •์  x ์‚ฌ์ด์˜ ๊ฒฝ๋กœ P1๋„ ์ตœ๋‹จ ๊ฒฝ๋กœ์ž„

 

=> ๋งŒ์ผ s์™€ x์‚ฌ์ด์— P1๋ณด๋‹ค ์งง์€ P2๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด, s์™€ e ์‚ฌ์ด์—๋Š” P๋ณด๋‹ค ์งง์€ ๊ฒฝ๋กœ๊ฐ€ ์กด์žฌํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๋ชจ์ˆœ!

 

Discussion

 

  • ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” Heap์— ์ตœ๋Œ€ |E| ๊ฐœ์˜ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๊ณ  ์ด๋ฅผ ๋‹ค์‹œ ์ •์  ๊ฐœ์ˆ˜์ธ |E| ๋งŒํผ ๋ฐ˜๋ณตํ•˜๋ฏ€๋กœ O(|E|log|E|) ๋กœ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ
    |E| < |V|^2 ์ด๋ฏ€๋กœ O(|E|log|E|) = O(2|E|log|V|) = O(|E|log|V|) ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Œ

  • ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ greedy algorithm์ž„

    => ๋งค๋ฒˆ ํ›„๋ณด ์ค‘์—์„œ s์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ •์ ์„ ์„ ํƒํ•˜๋ฏ€๋กœ

  • ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ dynamic programming์ž„

    => ๊ฑฐ๋ฆฌ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๊ณ , ๊ธฐ์กด ๊ฑฐ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜๋ฏ€๋กœ 

 

  • ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜์— ์Œ์ˆ˜๊ฐ€ ํฌํ•จ๋  ๊ฒฝ์šฐ ์ž˜๋ชป ๋™์ž‘ํ•จ

    ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์Œ์˜ ๊ฐ€์ค‘์น˜๊ฐ€ ์žˆ๋Š” 2๊ฐ€์ง€ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ

    • ์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์ตœ๋‹จ๊ฒฝ๋กœ๊ฐ€ ์ •์˜๋˜์ง€ ์•Š๊ณ 

    • ์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜์ง€ ์•Š์ง€๋งŒ ์Œ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ–๋Š” ๊ฐ„์„ ์ด ์กด์žฌํ•˜๋ฉด ์ตœ๋‹จ๊ฒฝ๋กœ๊ฐ€ ์žˆ์ง€๋งŒ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋‹ต์„ ๋ชป์ฐพ์Œ

 

Bellman-Ford Algorithm

 

๋ฒจ๋งŒ-ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ Single Source Shortest Path๋“ค์„ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž„

 

๋‹ค์ต์ŠคํŠธ๋ผ์™€ ๋‹ค๋ฅด๊ฒŒ ์Œ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ํ—ˆ์šฉํ•จ

 

(์Œ์˜ ์‚ฌ์ดํด์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜)

 

 

 

๋ฐฉ์‹์€ ๋ชจ๋“  ๊ฐ„์„ ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ํƒ์ƒ‰ํ•˜์—ฌ ์‹œ์ž‘ ์ •์ ์—์„œ ๊ฐ ์ •์ ๊นŒ์ง€์˜ ์ตœ๋‹จ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•ด ๋‚˜๊ฐ€๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž„

 

1. ์‹œ์ž‘ ์ •์  s์˜ ์ตœ๋‹จ๊ฑฐ๋ฆฌ d[s]๋ฅผ 0์œผ๋กœ, ๋‚˜๋จธ์ง€ ์ •์  v์˜ ์ตœ๋‹จ๊ฑฐ๋ฆฌ d[v]๋ฅผ ๋ฌดํ•œ๋Œ€๋กœ ์ดˆ๊ธฐํ™”

 

2. ๋ชจ๋“  ๊ฐ„์„  (u, v, w_uv)์— ๋Œ€ํ•ด d[v]์™€ ๊ฒฝ๋กœ๋ฅผ ๊ฐฑ์‹ 

=> ์—ฌ๊ธฐ์„œ d[v] = min(d[v], d[u] + w_uv)

 

์œ„ 2๋ฒˆ ๊ณผ์ •์„ |V| - 1ํšŒ ๋ฐ˜๋ณตํ•˜๋ฉด๋˜๋Š”๋ฐ

 

๋ฐ˜๋ณต์ด ๋๋‚˜๊ณ  ๋งˆ์ง€๋ง‰ ๊ณผ์ •์œผ๋กœ ์Œ์˜ ์‚ฌ์ดํด์ด ์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•ด์•ผํ•จ

 

์ด๋Š” d[v] < d[u] + w_uv ์ธ ๊ฐ„์„  (u, v, w_uv)๊ฐ€ ์กด์žฌํ•˜๋ฉด ์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์Œ
(์œ„ ๊ทธ๋ฆผ์„ ์ฐธ๊ณ ํ•˜๋ฉด ์ดํ•ด๊ฐ€ ์‰ฌ์›€)

Discussion

 

pseudo ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด

 

# s : ์‹œ์ž‘์ •์ , n : ์ •์  ์ˆ˜, E : ๊ฐ„์„  ์ง‘ํ•ฉ

prev = [-1] * n  # ์ด์ „ ์ •์  (parent pointer tree)
d = [โˆž] * n  # s์™€์˜ ๊ฑฐ๋ฆฌ
d[s] = 0

for _ in range(n - 1) :
	for (u, v, w_uv) in E :
    	if d[u] + w_uv < d[v] :
        	d[v] = d[u] + w_uv   # dp์ž„์„ ์•Œ ์ˆ˜ ์žˆ์Œ
            prev[v] = u

for (u, v, w_uv) in E :
	if d[u] + w_uv < d[v] :
    	#์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๋Š” ๋œป

 

 

์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” for๋ฌธ์„ ๋ณด๋ฉด ์ง๊ด€์ ์œผ๋กœ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ, O(|E| * (|V| - 1)) = O(|V||E|) ์ž„

 

|V| - 1 ๋ฒˆ ๋ฐ˜๋ณตํ•˜๋Š” ์ด์œ 

 

๊ฒฝ๋กœ์— ํฌํ•จ๋œ ๊ฐ„์„  ์ˆ˜๋Š” ์ตœ๋Œ€ |V| - 1๊ฐœ ์ด๋ฏ€๋กœ!

 

(|V| - 1๊ฐœ ๋ณด๋‹ค ๋งŽ์œผ๋ฉด ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๋Š” ๋œป์ž„)

 

์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ

 

|V| - 1 ํšŒ ์ดํ›„์—๋„ ๋” ์งง์•„์ง€๋Š” ๊ฒฝ๋กœ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด ๊ทธ๊ฑด ์Œ์˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•œ๋‹ค๋Š” ๋œป์ด ๋จ

 

Correctness Analysis

 

 

 

m๋ฒˆ ๋ฐ˜๋ณต ํ›„์—๋Š” ์ตœ๋Œ€ m๊ฐœ์˜ ๊ฐ„์„ ์„ ์‚ฌ์šฉํ•ด์„œ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋‹จ ๊ฒฝ๋กœ๊ฐ€ ๊ณ„์‚ฐ๋จ

 

=> ์ตœ๋‹จ๊ฒฝ๋กœ์˜ ์ตœ๋Œ€ ๊ธธ์ด๋Š” |V| - 1 ์ด๋ฏ€๋กœ |V| - 1ํšŒ ๋ฐ˜๋ณต์—ฐ์‚ฐ ํ›„์—๋Š” ๋ชจ๋“  ์ •์ ์— ์ด๋ฅด๋Š” ์ตœ๋‹จ ๊ฒฝ๋กœ๊ฐ€ ๊ณ„์‚ฐ๋จ

๋ฐ˜์‘ํ˜•

'๐Ÿ”ฅ Algorithm' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

L14 - KMP Algorithm  (1) 2024.11.30
L13 - Topological Sorting  (0) 2024.11.29
L11 - Minimum Spanning Trees  (0) 2024.11.26
L10 - Disjoint Sets  (0) 2024.11.22
L09 - Greedy Algorithms  (1) 2024.11.03