Baekjoon #1507

Baekjoon #1507

1개의 풀이 · Java

문제 원문 보기 ↗

SOLUTION INFO

Java · Main.java

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

public class Main {
    public static void main(String[] args) {
        FastReader rd = new FastReader();
        int N = rd.nextInt();

        int[][] a1 = new int[N][N];
        int[][] a2 = new int[N][N];

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                a1[i][j] = rd.nextInt();
                a2[i][j] = a1[i][j];
            }
        }

        for (int k = 0; k < N; k++) {
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (i == j || j == k || k == i) continue;

                    if (a1[i][j] > a1[i][k] + a1[k][j]) {
                        System.out.println(-1);
                        return;
                    }

                    if (a1[i][j] == a1[i][k] + a1[k][j]) {
                        a2[i][j] = 0;
                    }
                }
            }
        }

        int sum = 0;
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                sum += a2[i][j];
            }
        }
        System.out.println(sum);
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}

SOLUTION DESCRIPTION

풀이 설명

1. 플로이드-워셜 응용 문제. 최단 경로의 결과가 입력 값으로 주어지고, 이를 기반으로 본래 사용된 간선을 확인한다. 2. 플로이드-워셜의 핵심은 현재 간선 비용보다 우회하여 오는 간선의 비용이 더 적은 경우 업데이트를 하는 것이다. 따라서 우회한 간선의 합이 현재의 간선 비용과 동일하다면, 우회한 간선 쪽을 반영한 것이라고 추론할 수 있다. 3. 우회한 간선이 반영된 경우를 `0` 으로 변경하자. 모든 탐색이 끝난 이후에도 `0` 이 아닌 간선이 본래 최단 경로를 결과를 찾기 위해 사용된 초기 간선이 된다. 4. 탐색 시, 현재 간선보다 우회한 간선의 합이 더 큰 경우, 최단 경로를 잘못 파악한 것으로 간주하고 `-1` 을 출력한다.