Algorithm/알고리즘

벨만 포드 알고리즘 : 비용이 음수인 간선이 있을 때 최단 경로 계산

gangintheremark 2024. 3. 5. 21:31
728x90

모든 간선의 비용이 양수일 때는 다익스트라 최단 경로 알고리즘을 사용하면 된다. 하지만 음수 간선이 포함된다면?

 

음수 간선이 있는 경우

  • 음수 간선 순환이 없는 경우
  • 음수 간선 순환이 있는 경우

벨만 포드 알고리즘은 음수 간선의 순환을 감지할 수 있으며 음의 간선이 포함된 상황에서 사용할 수 있다. 시간복잡도는O(VE)로 다익스트라 알고리즘에 비해 느리다.

동작과정

1. 출발 노드 설정
2. 최단 거리 테이블 초기화
3. V-1번 반복
    3-1. 전체 간선 E개를 하나씩 확인
    3-2. 각 간선을 거쳐 다른 노드로 가는 비용을 계산하여 최단 거리 테이블 갱신
4. 음수 간선 순환이 발생하는지 체크하고 싶다면 3번의 과정을 한 번 더 수행최단 거리 테이블이 갱신된다면 음수 간선 순환이 존재

다익스트라 vs 벨만 포드

  • 다익스트라 알고리즘 : 매번 방문하지 않은 노드 중에서 최단 거리가 가장 짧은 노드 선택
  • 벨만 포드 알고리즘 : 매번 모든 간선을 전부 확인. 시간은 오래 걸리지만 음수 간선 순환 탐지 가능
import java.io.*;
import java.util.*;

public class Main {
    static int n, m, INF = (int) 1e9;
    static ArrayList<Edge> graph;
    static int[] d;

    static class Edge {
        int v;
        int w;
        int cost;

        public Edge(int v, int w, int cost) {
            this.v = v;
            this.w = w;
            this.cost = cost;
        }
    }

    public static boolean BellmanFord(int start) {
        d[start] = 0;

        // 정점의 개수만큼 반복
        for (int i = 0; i < n; i++) {
            // 간선의 개수만큼 반복
            for (int j = 0; j < m; j++) {
                Edge edge = graph.get(j);

                // 현재 간선의 들어오는 정점에 대해 비교
                if (d[edge.v] != INF && d[edge.w] > d[edge.v] + edge.cost)
                    d[edge.w] = d[edge.v] + edge.cost;
            }
        }

        // 음의 가중치 확인
        for (int i = 0; i < m; i++) {
            Edge edge = graph.get(i); // 현재 간선

            // 현재 간선의 들어오는 정점에 대해 비교 => 더 작은 값이 생기면 음수 사이클 존재
            if (d[edge.v] != INF && d[edge.w] > d[edge.v] + edge.cost)
                return false;
        }

        return true;

    }

}
728x90