Bellman-Ford 알고리즘

2025. 12. 19. 11:15·Algorithm/Basics

최소 비용으로 출발 정점에서 도착 정점으로 가는 방법을 찾는 것, 근데 간선에 음수가 존재한다.

여기서는 출발 정점 1, 도착 정점 5
먼저 간선을 1번만 사용해서 갈 수 있는 경로가 있다고 가정하고 계산해 보고,

그다음엔 간선을 2번 사용해서 갈 수 있다고 가정하고 또 계산해 본다.
만약 간선을 2번 사용해서 가는 경로가 더 좋다면(dist가 더 작다면) 그 값으로 갱신한다.

이런 식으로 반복.

그럼 이 과정을 몇 번까지 반복하느냐?
정점이 5개라면, 최단 경로에서 사용할 수 있는 간선의 최대 개수는 4개(V-1)이다.
예를 들면 1→2→3→4→5처럼 모든 정점을 한 번씩 거쳐 가는 경우가 간선을 가장 많이 사용하는 경우다.

 

 

음의 사이클이 존재면 안된다는 전제 조건이 있다.

만약 음의 사이클이 없는한, 노드가 5개일 때 간선을 5개 이상 선택할 수 없다.
만약 간선을 5개 이상 사용해 더 좋은 경로가 나온다면, 이는 음의 사이클이 존재한다는 뜻이다.

만약 이 간선이 -3이 아니라 -9라면, 계속 갱신이 발생하게 된다.
그래서 5 → 4 → 3 → … 처럼 같은 경로를 계속 돌게 된다.
이 경우 비용이 계속 줄어들기 때문에, 이는 음의 사이클이 존재한

 

즉, 어떤 한 정점에서 다른 한 정점으로 갈 때 그래프의 정점 수가 n개라면, 가장 많이 간선을 사용하는 것은 n−1개이다.

 

출발 정점은 1번, 도착 정점은 5번으로 설정

초기 상태
초기화는 1번 정점의 비용을 0으로 두고, 나머지 정점들은 모두 무한대로 초기화한다.
각 값은 해당 정점까지 가는 비용

 

표의 1행은 간선을 1번만 사용해서 각 정점으로 갈 수 있는지를 확인한 결과이다.
1→2는 0+5이므로 갱신해 준다.
1→3도 0+4이므로 갱신해 준다.
하지만 3→4는 현재 3의 값이 무한대이므로 무한대+5가 되어 갱신되지 않는다.
4→2, 2→5, 4->5 역시 이전 값이 무한대이므로 마찬가지로 갱신되지 않는다.

간선을 한 개만 사용해서 갈 수 있는 비용은
2번 정점으로 가는 비용 5, 그리고 3번 정점으로 가는 비용 4뿐이다.

 

이번에는 2번째 행은 간선을 2개 사용했을 때
1→2는 다시 계산해도 0+5이므로 갱신하지 않는다.
1→3도 마찬가지로 갱신되지 않는다.

이제 2→3을 보면, 현재 2번 정점의 값은 5이다.
간선을 2개까지 사용하는 단계이므로 5에 -3을 더하면 2가 되고, 기존 값 4보다 작으므로 갱신한다.

다음으로 3→4를 보면, 2+5=7이 되어 기존 무한대보다 작으므로 갱신한다.
4→2는 현재 4번 정점의 값이 무한대이므로 갱신할 수 없다.
2→5는 5+13=18이 되어 기존 무한대보다 작으므로 18로 갱신한다.
4→5는 4번 정점 값이 아직 무한대이므로 갱신되지 않는다.

 

 

 

1->2,1->3도 확인한다. 

즉 벨만–포드 알고리즘은 매 단계마다 모든 간선을 다시 확인한다.

이전 단계에서 갱신된 값이 이번 단계에서 다른 경로의 출발점이 될 수 있기 때문

즉, 벨만–포드는 경로를 따라 이어서 계산하는 방식이 아니라,

매 단계마다 모든 간선을 하나씩 확인하며 거리를 갱신하는 알고리즘이다.

선 2개까지의 최소 비용이 완성

 

이제 간선을 3개 사용했을 때를 확인한다.

1→2는 여전히 비용이 5이므로 갱신할 것이 없다.
1→3은 기존 값이 4인데, 현재 값 2가 더 작으므로 갱신하지 않는다.
2→3 역시 값이 2로 동일하므로 갱신하지 않는다

 

3→4를 보면, 2+5=7이 되어 기존에 저장된 9보다 작으므로 갱신해 준다.
2→5는 값이 같아 갱신하지 않는다.
4→5는 9+7=16이 되어 기존 값보다 작으므로 갱신한다.

처음에 18이었던 값은 1→2→5 경로였지만,
이제는 간선 3개를 사용한 1→3→4→5 경로로 갱신된다.

현재 0, 5, 2, 7, 16은 가장 좋은 값으로 갱신된 상태이다.

마지막으로 간선을 4개 사용했을 때
3→4는 2+5=7 갱신X
4→2는 7+3=10 5보다 크므로 갱신X
4→5는 7+7=14 갱신된다. 

 

즉, 간선을 4개 사용하는 경로인 1→2→3→4→5가 더 좋은 경로가 된다.
따라서 최종 결과는 14를 출력하면 된다.

벨만–포드 알고리즘은 인접 리스트로 그래프를 구성할 필요가 없다.

그냥 간선을 순회하면서 반복적으로 적용하면 된다.

  • 정점 기준으로 퍼져나가는 구조가 아니다.
  • 간선 리스트가지고 dist 갱신만 하면 충분

 

또한 거리 정보는 1차원 distance 배열로 충분하다.

  • 거리 갱신은 이전 결과를 그대로 덮어쓰며 진행할 수 수 있다.

코드

//1️⃣ 간선 정보 입력
vector<Edge> Ed;
scanf("%d %d", &n, &m);
for(i=1; i<=m; i++){
    scanf("%d %d %d", &a, &b, &c);
    Ed.push_back(Edge(a,b,c));
}

//2️⃣ distance 배열 초기화
for(i=1; i<=n; i++){
    dist[i] = 2147000000;
}
scanf("%d %d", &s, &e);
dist[s] = 0;  // 출발 정점은 0으로 초기화

//3️⃣ 최단 거리 갱신 (V-1번 반복)
//i가 1이면 간선을 1번만 사용하는 경우
//i가 2이면 간선을 2번만 사용하는 경우 
for(i=1; i<n; i++){
    for(j=0; j<Ed.size(); j++){
        int u = Ed[j].s;
        int v = Ed[j].e;
        int w = Ed[j].val;

        if(dist[u] != 2147000000 && dist[u] + w < dist[v]){//출발이 무한대이면 하지 않는다. 
		//그리고 출발하는 값에 가중치 더한값이 기존값보다 작으면 값을 갱신해준다.  
            dist[v] = dist[u] + w;
        }
    }
}
//이렇게 하면distance 배열에 최소 비용값이 저장된다. 

//4️⃣ 음의 사이클 검사
//간선을 n번 했을 때 있는지 확인하는 것이다.
for(j=0; j<Ed.size(); j++){
    int u = Ed[j].s;
    int v = Ed[j].e;
    int w = Ed[j].val;

    if(dist[u] != 2147000000 && dist[u] + w < dist[v]){
        printf("-1\n");
    }
}

//5️⃣ 최종 결과 출력
printf("%d\n", dist[e]);

 

 

 

 

 

출처: it 취업을 위한 알고리즘 문제풀이 입문 (with C/C++)

'Algorithm > Basics' 카테고리의 다른 글

Topology Sort 알고리즘  (0) 2025.12.26
Floyd-Warshall 알고리즘  (0) 2025.12.26
Dijkstra 알고리즘  (0) 2025.12.17
Minimum Spanning Tree 알고리즘  (0) 2025.12.16
Union-Find 알고리즘  (0) 2025.12.16
'Algorithm/Basics' 카테고리의 다른 글
  • Topology Sort 알고리즘
  • Floyd-Warshall 알고리즘
  • Dijkstra 알고리즘
  • Minimum Spanning Tree 알고리즘
dev.di
dev.di
devdi 님의 블로그 입니다.
  • dev.di
    개발 블로그
    dev.di
  • 전체
    오늘
    어제
    • 분류 전체보기 (28)
      • Algorithm (9)
        • Basics (9)
      • AWS (0)
        • AWS (0)
        • SAA (0)
      • Computer Science (1)
        • OS 벼락치기 (1)
        • DB 벼락치기 (0)
      • Data Engineer (8)
        • Airflow (0)
        • Data Warehouse (0)
        • Kafka (0)
        • Spark (0)
        • 데브코스 (8)
      • Docker (0)
      • Interviews (1)
      • Network (2)
        • Physical Layer (0)
        • Data Link Layer (0)
      • OOP (3)
        • GoF (3)
      • Python (4)
        • Django (3)
        • Scraping (1)
      • Software Engineering (0)
      • Spring (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    데이터 웨어하우스
    sql
    IPv4
    포트포워딩
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev.di
Bellman-Ford 알고리즘
상단으로

티스토리툴바