벨만-포드

  • 벨만-포드 알고리즘은 그래프에서 최단 거리를 구하는 알고리즘이다.

    • 특정 출발 노드에서 다른 모든 노드까지의 최단 경로 탐색

    • 음수 가중치 에지가 있어도 수행할 수 있음

    • 전체 그래프에서 음수 사이클의 존재 여부를 판단할 수 있음

    • O(VE) (노드 수 : V, 에지 수 : E)

타임머신으로 빨리 가기

Question - 11657

Code

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class N59_P11657_타임머신으로_빨리가기 {

    private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

    static int node, edge;

    static long[] distance;
    static cEdge edges[];

    public static void main(String[] args) throws IOException {
        StringTokenizer st = new StringTokenizer(br.readLine());
        node = Integer.parseInt(st.nextToken());
        edge = Integer.parseInt(st.nextToken());

        distance = new long[node + 1];
        edges = new cEdge[edge + 1];
        Arrays.fill(distance, Integer.MAX_VALUE);

        for (int i = 0; i < edge; i++) {
            st = new StringTokenizer(br.readLine());
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int time = Integer.parseInt(st.nextToken());
            edges[i] = new cEdge(start, end, time);
        }

        // bellman-ford-moore
        distance[1] = 0;
        for (int i = 1; i < node; i++) { // node보다 1개 적은 수만큼 반
            for (int j = 0; j < edge; j++) {
                cEdge now = edges[j]; //here
                if (distance[now.start] != Integer.MAX_VALUE
                        && distance[now.end] > distance[now.start] + now.time) {
                    distance[now.end] = distance[now.start] + now.time;
                }
            }
        }

        boolean mCycle = false;
        for (int i = 0; i < edge; i++) {
            cEdge now = edges[i];
            if (distance[now.start] != Integer.MAX_VALUE
                    && distance[now.end] > distance[now.start] + now.time) {
                mCycle = true;
            }
        }

        if (!mCycle) {
            for (int i = 2; i <= node; i++) {
                if (distance[i] == Integer.MAX_VALUE)
                    System.out.println("-1");
                else
                    System.out.println(distance[i]);
            }
        } else {
            System.out.println("-1");
        }
    }
}

class cEdge {
    int start, end, time;
    public cEdge(int start, int end, int time) {
         this.start = start;
         this.end = end;
         this.time = time;
    }
}

Insight

Idea

reference

세일즈맨의 고민

Question - 1219

Code

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class N60_P1219_세일즈맨의_고민 {

    static int node, veryStart, veryEnd, edge;

    static long[] earning;
    static long[] distance;

    static mEdge[] edgeList;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        node = Integer.parseInt(st.nextToken());
        veryStart = Integer.parseInt(st.nextToken());
        veryEnd = Integer.parseInt(st.nextToken());
        edge = Integer.parseInt(st.nextToken());

        edgeList = new mEdge[edge];
        earning = new long[node]; // 각 도시에서 벌 수 있는 돈
        distance = new long[node];
        Arrays.fill(distance, Long.MIN_VALUE);

        for (int i = 0; i < edge; i++) {
            st = new StringTokenizer(br.readLine());
            int s = Integer.parseInt(st.nextToken());
            int e = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            edgeList[i] = new mEdge(s, e, c);
        }

        st = new StringTokenizer(br.readLine());
        for (int i = 0; i < node; i++) {
            earning[i] = Long.parseLong(st.nextToken());
        }

        // 변형된 벨만 포드
        distance[veryStart] = earning[veryStart];

        for (int i = 0; i <= node + 100; i++) {
            for (int j = 0; j < edge; j++) {
                int start = edgeList[j].start;
                int end = edgeList[j].end;
                int cost = edgeList[j].cost;

                // 출발 노드가 방문하지 않은 노드 skip
                if (distance[start] == Long.MIN_VALUE) continue;

                // 출발 노드가 양수 사이클에 연결되 노드라면 동료 노드도 연결 노드로 업데이트
                else if (distance[start] == Long.MAX_VALUE)
                    distance[end] = Long.MAX_VALUE;

                // 더 많은 돈을 벌 수 있는 새로운 경로 발견됐을 때 새로운 경로값으로 업데이트
                else if (distance[end] < distance[start] + earning[end] - cost) {
                    distance[end] = distance[start] + earning[end] -cost;
                    if (i >= node -1) distance[end] = Long.MAX_VALUE;
                }
            }
        }

        // 도착 불가능
        if (distance[veryEnd] == Long.MIN_VALUE) System.out.println("gg");

        // 양수 사이클 연결돼 무한대 돈을 벌수 있을 때
        else if (distance[veryEnd] == Long.MAX_VALUE) System.out.println("Gee");

        // 이외
        else System.out.println(distance[veryEnd]);
    }
}

class mEdge {
    int start, end, cost;
    public mEdge(int start, int end, int cost) {
        this.start = start;
        this.end = end;
        this.cost = cost;
    }
}

Insight

Idea

  • 그래프 이론

  • 그래프 탐색

  • 벨만-포드

reference

Last updated