새소식

항해 99 TIL

99클럽 코테 스터디 29일차 TIL [BellmanFord]

  • -

[문제 이름 : 타임 머신(백준 , G4)]
문제 url : https://www.acmicpc.net/problem/11657

내가 작성한 코드는 아래와 같다.

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

public class Main {
    static ArrayList<Node>[] A;
    static int n,m;
    static long[] dist;
    static final long INF = Long.MAX_VALUE;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        // 도시 개수
        n = Integer.parseInt(st.nextToken());
        // 버스 노선 개수
        m = Integer.parseInt(st.nextToken());

        A = new ArrayList[n+1];
        for(int i=1; i<=n; i++) {
            A[i] = new ArrayList<>();
        }

        for(int i=0; i<m; i++) {
            st = new StringTokenizer(br.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int cost = Integer.parseInt(st.nextToken());
            A[start].add(new Node(end, cost));
        }

        if(!bellmanFord(1)) {
            // 음수 사이클 존재하는 경우
            System.out.println(-1);
        } else {
            for(int i=2; i<=n; i++) {
                if(dist[i] == INF) {
                    // 도달 불가능한 경우
                    System.out.println(-1);
                } else {
                    System.out.println(dist[i]);
                }
            }
        }
    }

    static boolean bellmanFord(int start) {
        dist = new long[n+1];
        Arrays.fill(dist, INF);
        dist[start] = 0;

        for(int i=1; i<n; i++) {
            for(int j=1; j<=n; j++) {
                for(Node node : A[j]) {
                    if(dist[j] != INF && dist[node.end] > dist[j] + node.cost) {
                        dist[node.end] = dist[j] + node.cost;
                    }
                }
            }
        }

        // 음수 사이클 체크
        for(int j=1; j<=n; j++) {
            for(Node node : A[j]) {
                if(dist[j] != INF && dist[node.end] > dist[j] + node.cost) {
                    return false;
                }
            }
        }

        return true;
    }

    static class Node {
        int end;
        int cost;

        Node(int end, int cost) {
            this.end = end;
            this.cost = cost;
        }
    }
}

음수 가중치가 존재하고, 사이클 여부를 확인하라는 말이 문제에 내포되어 있어 벨만포드 알고리즘을 사용해야 한다는 것을 빠르게 파악할 수 있었다.

 

1. 출발 정점, 도착 정점, 시간을 저장하는 ArrayList<Node>[] A를 선언하고, 입력값을 저장한다.

2. 벨만 포드 알고리즘을 사용한다. 초기에는 모두 INF로 값을 초기화한 다음, 출발 정점의 거리만 0으로 저장한다. 이후, 각 정점에서 이동 가능한 거리에 대해 계속 값을 갱신해 나간다.

3. 벨만포드 알고리즘 수행 이후, 음수 사이클을 체크해야 한다. 최단 거리가 갱신된 시점에서 한 번 더 이를 수행하여 거리가 갱신된다면, 이는 사이클이 있는 것을 의미한다.

for(int j=1; j<=n; j++) {
    for(Node node : A[j]) {
        if(dist[j] != INF && dist[node.end] > dist[j] + node.cost) {
            return false;
        }
    }
}

 4. 조건에 따라 각 줄에 1번 도시에서 출발해 2번 도시, 3번 도시, ..., N번 도시로 가는 가장 빠른 시간을 순서대로 출력한다. 

 

벨만포드 알고리즘이란?

  • 단일 시작점 최단 경로 알고리즘으로, 음수 가중치가 포함된 그래프에서 최단 경로를 계산할 때 사용된다.
  • 현재 노드에서 모든 정점과의 거리를 비교했을 때, 최소가 되는 간선을 통해 도달 가능한 거리의 합을 도출한다.
  • 이렇게 해서 최단 경로를 구했음에도 불구하고, 다시 한번 각 정점에서 최단 거리를 갱신했을 때 갱신된다면, 이는 음수 사이클이 존재함을 의미한다.


    내일은 대한항공 자기소개서를 작성할 예정이다.
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.