Algorithm

๋‹ค์ต์ŠคํŠธ๋ผ , ๋ฒจ๋งŒ-ํฌ๋“œ, ํ”Œ๋กœ์ด๋“œ-์›Œ์ƒฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฐจ์ด

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2024. 9. 20.

๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ฃผ์–ด์ง„ ๊ทธ๋ž˜ํ”„์˜ ์ •์ (Vertex)๊ณผ ๊ฐ„์„ (Edge)์„ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ BFS ์™€ DFS ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ BFS ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ BFS ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜๊ฐ€ ํ•ญ์ƒ ์ผ์ •ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ ์ตœ์„ ์˜ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ๋Š” ๋‹ค์ต์ŠคํŠธ๋ผ , ๋ฒจ๋งŒ-ํฌ๋“œ, ํ”Œ๋กœ์ด๋“œ-์›Œ์ƒฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ์˜ ์ฐจ์ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Dijkstra's Algorithm)

์ฃผ์–ด์ง„ ์‹œ์ž‘ ์ •์ ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์ ๊นŒ์ง€์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์ค‘์น˜๊ฐ€ ๋ชจ๋‘ ์–‘์ˆ˜์ธ ๊ฒฝ์šฐ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„: O((V + E) log V) (์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ)

์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋ก€๋„ค๋น„๊ฒŒ์ด์…˜ ์‹œ์Šคํ…œ์—์„œ ์ตœ๋‹จ ๊ฒฝ๋กœ ๊ณ„์‚ฐ, ํŒจํ‚ท ์ „๋‹ฌ ๊ฒฝ๋กœ ์ตœ์ ํ™”, ๊ฒŒ์ž„์—์„œ ์บ๋ฆญํ„ฐ ์ด๋™ ๊ฒฝ๋กœ ๊ณ„์‚ฐ

์•„๋ž˜๋Š” ๋‹ค์ต์ŠคํŠธ๋ผ์˜ ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค. ์šฐ์„ ์ˆœ์œ„ํ์™€ distance ๋ฐฐ์—ด์„ ๋ฌดํ•œ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ์‹œ์ผœ๋‘๊ณ  ์ด๊ฒƒ์„ ๋…ธ๋“œ์™€ ๋…ธ๋“œ๊ฐ€ ์—ฐ๊ฒฐ ๋œ๊ฑธ ๋ฐฉ๋ฌธํ•˜๋ฉด์„œ ์ตœ๋‹จ ๊ฒฝ๋กœ๋กœ ์ˆ˜์ •์‹œ์ผœ์ฃผ๋Š” ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

 

	int start = 1;
        int[] dist = new int[N + 1];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[start] = 0;
        
        PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
        pq.offer(new int[]{start, 0});
        
        while(!pq.isEmpty()){
            int[] current = pq.poll();
            int node = current[0];
            int cost = current[1];
            
            if(cost > dist[node]) continue;
            
            for(Edge edge : graph.get(node)){
                if(dist[edge.to] > dist[node] + edge.weight){
                    dist[edge.to] = dist[node] + edge.weight;
                    pq.offer(new int[]{edge.to, dist[edge.to]});
                }
            }
        }

๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์œ„ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ 5 → 2 ๊ฐ€์ค‘์น˜๊ฐ€ 1์—์„œ -2 ๋กœ ๋ณ€ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

์•„์ง๊นŒ์ง€ ์—ฌ์ „ํžˆ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ -2๋ณด๋‹ค ์ข€ ๋” ํฐ ์Œ์ˆ˜์ธ -4๋กœ ๋ฐ”๋€๋‹ค๋ฉด ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ๋Œ€ํ•œ ๊ฒฐ๊ณผ๋Š” ์•„๋ž˜ ๊ฐ™์ด ๋ฐ”๋€๋‹ˆ๋‹ค.

 

์ด๋ ‡๊ฒŒ ์Œ์ˆ˜ ๊ฐ„์„ ์˜ ์ˆœํ™˜์ด ์ƒ๊ธฐ๊ฒŒ ๋˜๊ณ  ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๊ฐ€ ์Œ์˜ ๋ฌดํ•œ์ธ ๋…ธ๋“œ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ๊ทธ ๋…ธ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๋‹ค๋ฅธ ๋…ธ๋“œ๋ฅผ ๊ฐ€๊ฒŒ ๋์„ ๋•Œ๋„ -∞ + n ์ด๊ธฐ ๋•Œ๋ฌธ์—  -∞ ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์Œ์˜ ์ˆœํ™˜ ๊ณ ๋ฆฌ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋‹ค์ต์ŠคํŠธ๋ผ๋Š” ์Œ์˜ ๊ฐ„์„  ๊ฐ€์ค‘์น˜๊ฐ€ ์žˆ์„ ๋• ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

 

๋Œ€ํ‘œ ๋ฌธ์ œ

https://www.acmicpc.net/problem/1753

 

 

๋ฒจ๋งŒ-ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Bellman-Ford Algorithm)

์ฃผ์–ด์ง„ ์‹œ์ž‘ ์ •์ ์—์„œ ๋‹ค๋ฅธ ๋ชจ๋“  ์ •์ ๊นŒ์ง€์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฐ„์„ ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ฒ€์‚ฌํ•˜์—ฌ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. N-1๋ฒˆ์˜ ๋ฐ˜๋ณต์„ ํ†ตํ•ด ๋ชจ๋“  ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ๋ณด์žฅํ•˜๊ณ , ์ถ”๊ฐ€์ ์ธ ๋ฐ˜๋ณต์„ ํ†ตํ•ด ์Œ์ˆ˜ ์‚ฌ์ดํด์˜ ์กด์žฌ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.(์ด๋Ÿฌ๋ฏ€๋กœ ๋‹น์—ฐํžˆ ๋‹ค์ต์ŠคํŠธ๋ผ์—์„œ ๊ตฌํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์ ์˜ ํ•ด๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ๋‹ค์ต์ŠคํŠธ๋ผ๋ณด๋‹ค ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ํ›จ์”ฌ ๋งŽ์ด ๊ฑธ๋ฆฌ๊ธฐ์— ๊ฐ€์ค‘์น˜๊ฐ€ ์–‘์ˆ˜๋งŒ ์กด์žฌํ•œ๋‹ค๋ฉด ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๊ฒฝ์ œ์ ์ž…๋‹ˆ๋‹ค.)

  • ์Œ์˜ ๊ฐ€์ค‘์น˜๋„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ถ”๊ฐ€์ ์ธ ๋ฐ˜๋ณต์„ ํ†ตํ•ด ์Œ์ˆ˜ ์‚ฌ์ดํด์˜ ์กด์žฌ๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. N๋ฒˆ์งธ ๋ฐ˜๋ณต์—์„œ ์—ฌ์ „ํžˆ ๊ฑฐ๋ฆฌ๊ฐ€ ์—…๋ฐ์ดํŠธ๋œ๋‹ค๋ฉด ์Œ์ˆ˜ ์‚ฌ์ดํด์ด ์กด์žฌํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„: O(V * E) ๋ชจ๋“  ๊ฐ„์„ ์„ N-1๋ฒˆ ๋ฐ˜๋ณตํ•˜์—ฌ ๊ฒ€์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋…ธ๋“œ ์ˆ˜์™€ ๊ฐ„์„  ์ˆ˜์— ๋น„๋ก€ํ•˜๋Š” ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.

๋‹จ์ˆœ ๋ฆฌ์ŠคํŠธ ๋˜๋Š” ๋ฐฐ์—ด ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋ก€ : ๊ธˆ์œต ๋ชจ๋ธ๋ง, ์Œ์ˆ˜ ์‚ฌ์ดํด์ด ์žˆ๋Š” ๊ทธ๋ž˜ํ”„, ๊ธˆ์œต ์‹œ์Šคํ…œ์—์„œ ๋ฌดํ•œํ•œ ์ด๋“์„ ์–ป์„ ์ˆ˜ ์žˆ๋Š” ์‚ฌ์ดํด ๊ฐ์ง€

ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

	int start = 1;
        long[] dist = new long[N + 1];
        Arrays.fill(dist, Long.MAX_VALUE);
        dist[start] = 0;
        
        // ๋ฒจ๋งŒ-ํฌ๋“œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์‹คํ–‰
        for(int i = 1; i < N; i++) {
            for(Edge edge : edges){
                if(dist[edge.from] != Long.MAX_VALUE && dist[edge.to] > dist[edge.from] + edge.weight){
                    dist[edge.to] = dist[edge.from] + edge.weight;
                }
            }
        }
        
        // ์Œ์ˆ˜ ์‚ฌ์ดํด ๊ฐ์ง€
        boolean negativeCycle = false;
        for(Edge edge : edges){
            if(dist[edge.from] != Long.MAX_VALUE && dist[edge.to] > dist[edge.from] + edge.weight){
                negativeCycle = true;
                break;
            }
        }

 

๋Œ€ํ‘œ๋ฌธ์ œ

https://www.acmicpc.net/problem/11657

 

 

ํ”Œ๋กœ์ด๋“œ-์›Œ์…œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (Floyd-Warshall Algorithm)

๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์  ์Œ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.(๋‹จ์ผ ์‹œ์ž‘์  ์•„๋‹˜ ์ฃผ์˜)

๋ชจ๋“  ์ •์  ์Œ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์„ ๋•Œ์‚ฌ์šฉ๋˜๊ณ , ์Œ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์Œ์˜ ์‚ฌ์ดํด์ด ์—†๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”Œ๋กœ์ด๋“œ-์›Œ์ƒฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋™์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ(DP)์„ ์ด์šฉํ•ด ์ค‘๊ฐ„์— ๊ฒฝ์œ ํ•˜๋Š” ์ •์ ์„ ์ ์ง„์ ์œผ๋กœ ๋Š˜๋ ค๊ฐ€๋ฉฐ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

  1. ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์  ์Œ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ์ง์ ‘ ์—ฐ๊ฒฐ๋œ ๊ฐ„์„ ์˜ ๊ฑฐ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ๋ฌดํ•œ๋Œ€๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ฐ ์ •์ ์„ ์ค‘๊ฐ„ ์ •์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์ •์  ์Œ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.
  3. ์ค‘๊ฐ„ ์ •์ ์„ ํ†ตํ•ด ๋” ์งง์€ ๊ฒฝ๋กœ๊ฐ€ ๋ฐœ๊ฒฌ๋˜๋ฉด ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„ ๋ณต์žก๋„: O(V^3)

์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‚ฌ๋ก€ : ๋ชจ๋“  ์Œ ์ตœ๋‹จ ๊ฒฝ๋กœ ๋ฌธ์ œ(๋ชจ๋“  ์ •์  ์Œ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ), ๋„คํŠธ์›Œํฌ ๋‚ด ๋ชจ๋“  ์ปดํ“จํ„ฐ ๊ฐ„์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ๊ฒฝ์šฐ, ๊ตํ†ต ์‹œ์Šคํ…œ(๋„์‹œ ๊ฐ„์˜ ๋ชจ๋“  ๊ฒฝ๋กœ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ์ตœ๋‹จ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๋Š” ๊ฒฝ์šฐ)

ํ•ต์‹ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

	int[][] dist = {
            {0, 5, INF, 8},
            {7, 0, 9, INF},
            {2, INF, 0, 4},
            {INF, INF, 3, 0}
        };

        // ํ”Œ๋กœ์ด๋“œ-์›Œ์ƒฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜
        for (int k = 0; k < N; k++) { // ์ค‘๊ฐ„์— ๊ฒฝ์œ ํ•˜๋Š” ๋…ธ๋“œ
            for (int i = 0; i < N; i++) { // ์‹œ์ž‘ ๋…ธ๋“œ
                for (int j = 0; j < N; j++) { // ๋„์ฐฉ ๋…ธ๋“œ
                    if (dist[i][j] > dist[i][k] + dist[k][j]) {
                        dist[i][j] = dist[i][k] + dist[k][j];
                    }
                }
            }
        }

 

๋Œ€ํ‘œ ๋ฌธ์ œ

https://www.acmicpc.net/problem/11404

 

์š”์•ฝ

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ๋ฌด๋ฐฉํ–ฅ์„ฑ ๊ทธ๋ž˜ํ”„ ์Œ์ˆ˜ ๊ฐ€์ค‘์น˜ ๊ฐ„์„  ์Œ์ˆ˜ ์‚ฌ์ดํด ๊ฐ์ง€
๋‹ค์ต์ŠคํŠธ๋ผ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ ๋ถˆ๊ฐ€๋Šฅ ๋ถˆ๊ฐ€๋Šฅ
๋ฒจ๋งŒ-ํฌ๋“œ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ
ํ”Œ๋กœ์ด๋“œ-์›Œ์ƒฌ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ ๊ฐ€๋Šฅ(์Œ์ˆ˜ ์‚ฌ์ดํด ์—†์„ ์‹œ) ๋ถˆ๊ฐ€๋Šฅ

 

๋Œ“๊ธ€