Graph ๊ธ€ ์ฐธ๊ณ ํ•˜๊ธฐ

Queue ๊ธ€ ์ฐธ๊ณ ํ•˜๊ธฐ


SPFA(Shortest Path Faster Algorithm)

The Shortest Path Faster Algorithm (SPFA)๋Š” Bellmanโ€“Ford algorithm ์„ ๊ฐœ์„ ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์œผ๋กœ์„œ, ๋ฐฉํ–ฅ ๊ฐ€์ค‘์น˜ ๊ทธ๋ž˜ํ”„์—์„œ ๋‹จ์ผ ์ถœ๋ฐœ ์ •์  ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ(Single source shortest path distance) ๊ณ„์‚ฐํ•œ๋‹ค. ๋‹ค๋ฅธ ์—ฌํƒ€ Bellmanโ€“Ford algorithm ์ด๋‚˜ Dijkstraโ€™s algorithm ๊ณผ ๊ฐ™์€ Single source shortest path algorithm ์ฒ˜๋Ÿผ SPFA๋„ ๋ณ€ ๊ฒฝ๊ฐ(Edge relaxation)์„ ํ•ต์‹ฌ ์—ฐ์‚ฐ์œผ๋กœ ํ•˜์—ฌ ๋™์ž‘ํ•œ๋‹ค.

์ด SPFA๋Š” ๋ฌด์ž‘์œ„ ํฌ์†Œ ๊ทธ๋ž˜ํ”„์—์„œ ์ž˜ ๋™์ž‘ํ•œ๋‹ค๊ณ  ์•Œ๋ ค์ ธ ์žˆ๊ณ , ์Œ์ˆ˜ ๊ฐ€์ค‘์น˜ ๊ฐ„์„ (Nagative weighted edge)์„ ๊ฐ€์ง„ ๊ทธ๋ž˜ํ”„์—์„œ๋„ ์ ํ•ฉํ•˜๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ตœ์•… ์‹œ๊ฐ„๋ณต์žก๋„๋Š” $O(|V|\cdot|E|)$ ๋กœ์„œ Bellmanโ€“Ford algorithm๊ณผ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์—, ์Œ์ˆ˜ ๊ฐ€์ค‘์น˜ ๊ฐ„์„ ์ด ์—†๋Š” ๊ทธ๋ž˜ํ”„์˜ ๊ฒฝ์šฐ์—๋Š” ์ตœ์•… ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ณ ๋ คํ•œ๋‹ค๋ฉด Dijkstraโ€™s algorithm์ด ๋” ์ ํ•ฉํ•˜๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Algorithm

๋ฐฉํ–ฅ ๊ฐ€์ค‘์น˜ ๊ทธ๋ž˜ํ”„๊ฐ€ ์ฃผ์–ด์ง€๊ณ  $G = (V, E)$ ๊ทธ๋ฆฌ๊ณ  ์ถœ๋ฐœ ์ •์ ์„ $s$๋ผ๊ณ  ํ•˜์ž. SPFA๋Š” ์ถœ๋ฐœ ์ •์  $s$์œผ๋กœ๋ถ€ํ„ฐ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์  $v$๋กœ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š”๋‹ค. $s$๋กœ ๋ถ€ํ„ฐ $v$๋กœ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ๋Š” ๊ฐ ์ •์  $v$์— ๋Œ€ํ•˜์—ฌ $d(v)$์— ์ €์žฅ๋œ๋‹ค.

SPFA๋Š” ๊ฐ ์ •์ ์˜ ์ธ์ ‘ ์ •์ ์„ ํ•„์š”ํ•˜๋‹ค๋ฉด ๋ณ€ ๊ฒฝ๊ฐ(Edge relaxation)ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ์ •์ ์„ ํ›„๋ณด์ž๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ์ ์€ Bellmanโ€“Ford algorithm๊ณผ ๊ฐ™๋‹ค. ํ•˜์ง€๋งŒ Bellmanโ€“Ford algorithm๊ณผ ๋น„๊ตํ–ˆ์„ ๋•Œ์˜ ๊ฐœ์„ ์ ์€ ๋ชจ๋“  ์ •์ ๋“ค์„ ๋ฌด์กฐ๊ฑด ์ ์œผ๋กœ ์—ฐ์‚ฐ์„ ์‹œ๋„ํ•˜๊ธฐ ๋ณด๋‹ค๋Š” SPFA๋Š” ํ›„๋ณด์ž ์ •์ ์— ๋Œ€ํ•œ Queue๋ฅผ ๊ฐ€์ง€๊ณ , ์–ด๋–ค ์ •์ ์— ๋Œ€ํ•ด ๊ทธ ์ •์ ์ด ๋ณ€ ๊ฒฝ๊ฐ ์—ฐ์‚ฐ์ด ์ด๋ฃจ์–ด์กŒ์„ ๋•Œ๋งŒ ํ›„๋ณด์ž ์ •์ ์œผ๋กœ์„œ Queue์— ์‚ฝ์ž…์„ ํ•œ๋‹ค. ์ด๋Ÿฐ ํ–‰๋™๋“ค์€ ๋ณ€ ๊ฒฝ๊ฐ ์—ฐ์‚ฐ์ด ์‹คํ–‰๋  ์ •์ ์ด ์—†์„ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต๋œ๋‹ค.


๋‹ค์Œ์€ SPFA์˜ ์˜์‚ฌ์ฝ”๋“œ์ด๋‹ค.

Input: ๊ทธ๋ž˜ํ”„ G, ์‹œ์ž‘ ์ •์  s

$Q$๋Š” ๋ณ€ ๊ฒฝ๊ฐ ์—ฐ์‚ฐ์ด ๋˜๊ณ  ๋‚œ ํ›„์˜ ํ›„๋ณด์ž๋ฅผ ๋‹ด์„ Queue๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
$w(u,v)$๋Š” ๊ฐ„์„  $(u,v)$์˜ ๊ฐ„์„  ๊ฐ€์ค‘์น˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

Notice: Q ์•ˆ์— v์˜ ์กด์žฌ ์œ ๋ฌด๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌํ˜„ ์‹œ์—๋Š” ์ด๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์š”๊ตฌ๋œ๋‹ค.

 0 procedure Shortest-Path-Faster-Algorithm(G, s)
 1    for each vertex v โ‰  s in V(G)
 2        d(v) := โˆž
 3    d(s) := 0
 4    offer s into Q
 5    while Q is not empty
 6        u := poll Q
 7        for each edge (u, v) in E(G)
 8            if d(u) + w(u, v) < d(v) then
 9                d(v) := d(u) + w(u, v)
10                if v is not in Q then
11                    offer v into Q

ํ•˜๋‚˜์”ฉ ๋ณด์ž.

1    for each vertex v โ‰  s in V(G)
2        d(v) := โˆž

๊ทธ๋ž˜ํ”„ G์˜ ์ถœ๋ฐœ ์ •์  s๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์ •์  v์— ๋Œ€ํ•˜์—ฌ s๋กœ๋ถ€ํ„ฐ ๊ฐ v์— ๋Œ€ํ•œ ์ตœ๋‹จ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ d(v)๋ฅผ INF๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.

 3    d(s) := 0
 4    offer s into Q

๋จผ์ € ์ถœ๋ฐœ ์ •์  s์˜ ์ตœ๋‹จ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ๋ฅผ 0์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  s๋ฅผ Q์— ๋„ฃ๋Š”๋‹ค.

5    while Q is not empty

ํ๊ฐ€ ๋นŒ ๋•Œ ๊นŒ์ง€ ์•„๋ž˜ ์—ฐ์‚ฐ๋“ค์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

6    u := poll Q
7    for each edge (u, v) in E(G)

Q์—์„œ ์ •์ ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด u๋ผ ํ•˜๊ณ , ๊ทธ๋ž˜ํ”„ G์—์„œ u์™€ ์ธ์ ‘ํ•œ ์ •์  v์™€์˜ ๊ฐ„์„  (u, v)์— ๋Œ€ํ•˜์—ฌ

8    if d(u) + w(u, v) < d(v) then
9       d(v) := d(u) + w(u, v)

s๋กœ๋ถ€ํ„ฐ u๋กœ์˜ ์ตœ๋‹จ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ d(u) + ๊ฐ„์„  (u, v)์˜ ๊ฐ’์ด s๋กœ๋ถ€ํ„ฐ v๋กœ์˜ ์ตœ๋‹จ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ d(v)๋ณด๋‹ค ์ž‘๋‹ค๋ฉด d(v)๊ฐ’์„ d(u) + w(u, v)๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค. (Edge Relaxation)

10      if v is not in Q then
11          offer v into Q

๋ณ€ ๊ฒฝ๊ฐ ์—ฐ์‚ฐ(Edge Relaxation)์ด ๋œ ์ •์  v๊ฐ€ ํ˜„์žฌ Q์— ์—†์œผ๋ฉด, v๋ฅผ Q์— ์ถ”๊ฐ€ํ•œ๋‹ค.

Step by step

์‹ค์ œ ๊ทธ๋ž˜ํ”„๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด SPFA๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

0๋ฒˆ์„ ์‹œ์ž‘ ์ •์ ์œผ๋กœ ํ•˜์—ฌ 5๋ฒˆ ์ •์ ์œผ๋กœ์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ๊ตฌํ•œ๋‹ค.

ํ•ด๋‹น ์ •์ ์— ์—ฐ๊ฒฐ๋œ ์ธ์ ‘ ์ •์ ์ด ์—ฌ๋Ÿฌ๊ฐœ ์ผ ๋•, ๋ฒˆํ˜ธ๊ฐ€ ์ž‘์€ ๊ฒƒ์„ ๋จผ์ € ์„ ํƒํ•œ๋‹ค.

Alt text

์‹œ์ž‘ ์ •์ ์œผ๋กœ ๋ถ€ํ„ฐ ๋ชจ๋“  ์ •์ ๊นŒ์ง€์˜ ์ตœ๋‹จ๊ฑฐ๋ฆฌ d(v)๋ฅผ ๋ฌดํ•œ๋Œ€(INF)๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.
d(s)๋Š” 0์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค.

Queue์— ์‹œ์ž‘ ์ •์  0์„ ๋„ฃ๋Š”๋‹ค.
Queue : [0]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
0๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  1๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(0) + w(0, 1) < d(1): 0 + 4 < INF์ด๋ฏ€๋กœ d(1)์„ 4๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 1๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [1]

Alt text

0๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  2๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(0) + w(0, 2) < d(1): 0 + 2 < INF์ด๋ฏ€๋กœ d(2)์„ 2๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 2๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [1 2]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
1๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  2๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(1) + w(1, 2) < d(2): 4 + 5 > 2์ด๋ฏ€๋กœ d(2)๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

Queue : [2]

Alt text

1๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  3๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(1) + w(1, 3) < d(3): 4 + 10 < INF์ด๋ฏ€๋กœ d(3)์„ 14๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 3๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [2, 3]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
2๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  4๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(2) + w(2, 4) < d(4): 2 + 3 < INF์ด๋ฏ€๋กœ d(4)์„ 5๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 4๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [3, 4]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
3๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  5๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(3) + w(3, 5) < d(5): 14 + 11 < INF์ด๋ฏ€๋กœ d(5)์„ 25๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 5๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [4, 5]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
4๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  3๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(4) + w(4, 3) < d(3): 5 + 4 < 14์ด๋ฏ€๋กœ d(3)์„ 9๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 3๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [5, 3]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
5๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์ ์ด ์—†๋‹ค.

Queue : [3]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
3๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์  5๋ฒˆ์— ๋Œ€ํ•˜์—ฌ d(3) + w(3, 5) < d(5): 9 + 11 < 25์ด๋ฏ€๋กœ d(5)์„ 20๋กœ ์—…๋ฐ์ดํŠธ ํ•œ๋‹ค.

์—…๋ฐ์ดํŠธ ๋˜์—ˆ์œผ๋ฏ€๋กœ 5๋ฒˆ ์ •์ ์„ Queue์— ๋„ฃ๋Š”๋‹ค.
Queue : [5]

Alt text

Queue์—์„œ ์›์†Œ ํ•˜๋‚˜๋ฅผ popํ•œ๋‹ค.
5๋ฒˆ ์ •์ ๊ณผ ์ธ์ ‘ํ•œ ์ •์ ์ด ์—†๋‹ค.

Queue : [ ]

Alt text

ํ๊ฐ€ ๋น„์—ˆ์œผ๋ฏ€๋กœ SPFA๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค.

0๋ฒˆ ๋ถ€ํ„ฐ 5๋ฒˆ์œผ๋กœ์˜ ์ตœ๋‹จ๊ฒฝ๋กœ๋Š” ๋นจ๊ฐ„์„ ์„ ๋”ฐ๋ผ๊ฐ„ ๊ฒฝ๋กœ์ด๊ณ  ๊ทธ ๊ฑฐ๋ฆฌ๋Š” 20์ด๋‹ค.

Alt text

Implementation

๋‹ค์Œ์€ ์œ„ ์˜์‚ฌ์ฝ”๋“œ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ SPFA๋ฅผ ๊ตฌํ˜„ํ•œ ์ž๋ฐ” ๋ฉ”์†Œ๋“œ์ด๋‹ค.

static void shortestPathFasterAlgorithm(int s){
    dist = new int[n];
    onQueue = new boolean[n];
    Arrays.fill(dist, INF);
    Queue<Integer> queue = new LinkedList<>();
    queue.offer(s);
    dist[s] = 0;
    onQueue[s] = true;
    while (!queue.isEmpty()){
        int cur = queue.poll();
        onQueue[cur] = false;
        for (Edge e : graph[cur]){
            if (dist[cur] + e.cost < dist[e.to]){
                dist[e.to] = dist[cur] + e.cost; // Edge Relaxation
            }
        }
    }
}

ํ˜„์žฌ Queue์—์„œ ์ •์  $v$์˜ ์กด์žฌ ์œ ๋ฌด๋ฅผ ์ถ”์ ํ•˜๊ธฐ ์œ„ํ•ด ์œ„ ์ฝ”๋“œ์—์„œ๋Š” onQueue[] ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.


๊ทธ๋ž˜ํ”„์˜ ๊ฐ€์ค‘์น˜ ๊ฐ„์„  ์ •๋ณด๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ Edge ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

to๋Š” ๋‹ค์Œ ์ธ์ ‘ ์ •์ ์˜ ๋ฒˆํ˜ธ, cost๋Š” ๊ฐ„์„  ๋น„์šฉ(๊ฐ€์ค‘์น˜)๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

...
// static ArrayList<Edge> [] graph;
...

static class Edge{
    int to;
    int cost;

    // Constructor
    public Edge(int to, int cost) {
        this.to = to;
        this.cost = cost;
    }
}

๋‹ค์Œ์€ SPFA๋ฅผ ๊ตฌํ˜„ํ•œ ์ž๋ฐ” ์ฝ”๋“œ์ด๋‹ค.

๊ทธ๋ž˜ํ”„์˜ ์ž…๋ ฅ์€ ์˜ˆ์ œ ๊ทธ๋ž˜ํ”„๋ฅผ ์‚ฌ์šฉํ•˜์˜€๊ณ , ์ตœ๋‹จ๊ฒฝ๋กœ๋ฅผ ์ถ”์ ํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด pred[]๋ฐฐ์—ด์„ ์„ ์–ธํ•œ ๋’ค SPFA์˜ ์‹คํ–‰ ์ค‘์— ์–ด๋А ํ•œ ํฌ์ธํŠธ์—์„œ ์ •์  u, v๊ฐ€ ์žˆ๊ณ (์ •์  v๊ฐ€ u์— ์˜ํ•ด relaxation ๋˜์–ด์ง€๋Š” ์ •์ ), relaxation ๋˜์–ด์ง„ ์ •์  v๊ฐ€ ์žˆ์œผ๋ฉด, ๊ทธ ์ •์ ์„ relaxationํ•˜๊ฒŒ ๋งŒ๋“  ์ •์  u๊ฐ€ ์ตœ๋‹จ๊ฒฝ๋กœ ์ƒ์˜ ์ด์ „ ๋…ธ๋“œ ์ด๋ฏ€๋กœ pred[e.to] = cur;๋ฅผ ํ•˜์—ฌ ๊ฒฝ๋กœ๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค. ๊ทธ ๋‹ค์Œ printPathReconstructionํ•จ์ˆ˜๋กœ ๊ฒฝ๋กœ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

์ด ํ”„๋กœ๊ทธ๋žจ์€ ์ตœ๋‹จ๊ฒฝ๋กœ ๊ฑฐ๋ฆฌ์™€ ๊ทธ ๊ฒฝ๋กœ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

  • Input: Graph G, start vertex
  • Output: Distance of shortest path of Graph G, shortest path of Graph G

์‹œ์ž‘ ์ •์ ์€ 0๋ฒˆ์ด๋‹ค.

import java.io.*;
import java.util.*;
import java.util.LinkedList;

/**
 * This program is to find Shortest path in weighted graph using SPFA.
 * Time Complexity : Worst case : O(VE) same as Standard Bellman ford
 *                   Average case : O(E) - not proved
 *
 * @author Lemidia(Gyeong)
 */

public class ShortestPathFasterAlgorithm{

     // the number of vertices in Graph G
    static int n;
    // Shortest distance from s to each vertex v
    static int dist[];
    // for construct shortest path
    static int pred[];
    static ArrayList<Edge> [] graph;
    static final int INF = Integer.MAX_VALUE;
    // For check whether the vertex is on queue or not
    static boolean onQueue[];


    // Init Graph G
    static void createGraph(){
        graph = new ArrayList[n];
        for (int i = 0; i < n; i++){
            graph[i] = new ArrayList<>();
        }
    }

    // Add weighted direct edges.
    static void addEdge(int from, int to, int cost){
        Edge e = new Edge(to, cost);
        graph[from].add(e);
    }

    static void shortestPathFasterAlgorithm(int s){
        dist = new int[n];
        pred = new int[n];
        onQueue = new boolean[n];
        Arrays.fill(dist, INF);
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(s);
        dist[s] = 0;
        onQueue[s] = true;
        while (!queue.isEmpty()){
            int cur = queue.poll();
            onQueue[cur] = false;
            for (Edge e : graph[cur]){
                if (dist[cur] + e.cost < dist[e.to]){
                    dist[e.to] = dist[cur] + e.cost; // Edge Relaxation
                    pred[e.to] = cur; // store previous node
                    if (onQueue[e.to] == false){ // Node(e.to) is not in the queue
                        onQueue[e.to] = true;
                        queue.offer(e.to);
                    }
                }
            }
        }
    }

    static void printPathReconstruction(int start, int end){
        if (end == start) {
            System.out.print(start);
            return;
        }
        pathReconstruction(start, pred[end]);
        System.out.print(" -> " + end );
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        n = 6;
        int start = 0;
        createGraph();
        addEdge(0, 1, 4);
        addEdge(0, 2, 2);
        addEdge(1, 2, 5);
        addEdge(1, 3, 10);
        addEdge(2, 4, 3);
        addEdge(3, 5, 11);
        addEdge(4, 3, 4);

        shortestPathFasterAlgorithm(start);

        System.out.println("Shortest path distance : " + dist[5]);
        System.out.print("Shortest path : ");
        printPathReconstruction(start, 5);
    }

    static class Edge{
        int to;
        int cost;

        public Edge(int to, int cost) {
            this.to = to;
            this.cost = cost;
        }
    }
}
Output:

Shortest path distance : 20
Shortest path : 0 -> 2 -> 4 -> 3 -> 5

Optimization techniques

Small Label First (SLF) technique.

๋ณ€ ๊ฒฝ๊ฐ(Edge relaxation) ๋˜์–ด์ง„ ์ •์  $v$๋ฅผ ํ•ญ์ƒ Queue ๋’ค์— ์ถ”๊ฐ€ํ•˜์˜€์ง€๋งŒ ์ด technique์—์„œ๋Š” ๊ทธ ์ถ”๊ฐ€๋˜์–ด์ง„ ์ •์  $v$์˜ $d(v)$์™€ Queue์˜ ๋งจ ์•ž ์ •์ ์˜ ๊ฑฐ๋ฆฌ $d(front(Q))$๋ฅผ ๋น„๊ตํ•˜๊ณ  $d(v)$๊ฐ€ ๋” ์ž‘๋‹ค๋ฉด $d(v)$๋ฅผ Queue์˜ ๋งจ ์•ž์œผ๋กœ ๋ณด๋‚ธ๋‹ค. ์ด technique์€ front์— ์›์†Œ ์ถ”๊ฐ€๋ฅผ ์š”๊ตฌํ•˜๋ฏ€๋กœ front์™€ rear ์ „๋ถ€ pop(), offer()์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋Š” Deque(๋ฐํฌ) ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„ SPFA ์ž๋ฐ” ๋ฉ”์†Œ๋“œ์—์„œ Queue<Integer> queue = new LinkedList<>();๋ฅผ Deque<Integer> queue = new LinkedList<>();๋กœ ํ•˜์—ฌ Deque๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

๋‹ค์Œ์€ ์ด technique์˜ ์˜์‚ฌ์ฝ”๋“œ์ด๋‹ค.

procedure Small-Label-First(G, Q)
     if d(back(Q)) < d(front(Q)) then
         u := pop back of Q
         push u into front of Q

๋‹ค์Œ์€ SPFA์— ์œ„ ์ตœ์ ํ™”๋ฅผ ์ ์šฉํ•œ ์ฝ”๋“œ์ด๋‹ค.

static void shortestPathFasterAlgorithm(int s){
    dist = new int[n];
    pred = new int[n];
    onQueue = new boolean[n];
    Arrays.fill(dist, INF);
    Deque<Integer> queue = new LinkedList<>();
    queue.offer(s);
    dist[s] = 0;
    onQueue[s] = true;
    while (!queue.isEmpty()){
        int cur = queue.poll();
        onQueue[cur] = false;
        for (Edge e : graph[cur]){
            if (dist[cur] + e.cost < dist[e.to]){
                dist[e.to] = dist[cur] + e.cost; // Edge Relaxation
                pred[e.to] = cur; // store previous node
                if (onQueue[e.to] == false){ // Node(e.to) is not in the queue
                    onQueue[e.to] = true;
                    queue.offer(e.to);
                    // Optimization <Small Label First>
                    if (dist[e.to] < dist[queue.peekFirst()]){
                        queue.offerFirst(queue.pollLast());
                    }
                }
            }
        }
    }
}

Large Label Last (LLL) technique.

Queue์˜ front ์›์†Œ์˜ ๊ฐ’์ด ํ˜„์žฌ Queue์— ๋“ค์–ด์žˆ๋Š” ๋ชจ๋“  ์ •์ ์˜ ํ‰๊ท ๋ณด๋‹ค ์ž‘๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด, Queue์— ๋“ค์–ด์žˆ๋Š” ๋ชจ๋“œ ์ •์  $v$์˜ ํ‰๊ท ์„ ๊ตฌํ•˜๊ณ , Queue ์•ž์—์„œ ๋ถ€ํ„ฐ ํ‰๊ท ๋ณด๋‹ค ํฐ ๊ฐ’์„ ๊ฐ€์ง„ ์ •์  $v$๋“ค์„ Queue์˜ ๋งจ ๋’ค๋กœ ๋ณด๋‚ด๋Š” ์—ฐ์‚ฐ์ด๋‹ค. ํ‰๊ท ๋ณด๋‹ค ์ž‘์€ ๊ฐ’์„ ๊ฐ€์ง„ ์ •์  $v$๊ฐ€ ๋‚˜์˜ค๋ฉด loop๋ฅผ ๋น ์ ธ๋‚˜์˜จ๋‹ค.

๋‹ค์Œ์€ ์ด technique์˜ ์˜์‚ฌ์ฝ”๋“œ์ด๋‹ค.

 procedure Large-Label-Last(G, Q)
     x := average of d(v) for all v in Q
     while d(front(Q)) > x
         u := pop front of Q
         push u to back of Q

Running time

The worst-case running time : $O(|V|\cdot|E|)$

SPFA์˜ ์ตœ์•… ์‹คํ–‰ ์‹œ๊ฐ„์€ standard Bellman-Ford algorithm๊ณผ ๊ฐ™์€ $O(|V|\cdot|E|)$ ์ด๋‹ค.

The average running time : $O(|E|)$

์‹คํ—˜์œผ๋กœ ๋ณด์—ฌ์ง€๋Š” SPFA์˜ ํ‰๊ท  ์‹คํ–‰ ์‹œ๊ฐ„์€ $O(|E|)$ ์ˆ˜์ค€์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ‰๊ท  ์‹คํ–‰ ์‹œ๊ฐ„์€ ์•„์ง ์ฆ๋ช… ๋˜์ง€ ์•Š์•˜๋‹ค.

References

Leave a comment