Coding Test/Baekjoon

백준/11404번/Java - 플로이드 (플로이드-와샬)

grogu.... 2023. 10. 7. 12:47

https://www.acmicpc.net/problem/11404

 

11404번: 플로이드

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가

www.acmicpc.net


최소비용 배열 전체를 구하는 문제로, 플로이드-와샬 알고리즘을 적용하여 푼다.

 

전체 경로가 최단 경로이기 위해서는 전체 경로를 이루는 부분 경로들 역시 최단 경로를 이뤄야 한다는 점을 이용한다.

 

다익스트라는 인접리스트를, 벨만-포드는 간선배열을 활용했지만 플로이드-워셜은 인접행렬을 통해 문제를 푼다.

 

인접 행렬에 i노드에서 j노드까지의 가중치를 표시하고, 간선이 연결되지 않은 경우에는 무한대를 표시한다.

 

이후 플로이드 와샬 알고리즘을 실행한다.

 

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

public class Main {

    //최소비용 배열
    static long[][] D;

    static int N, M;

    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;
        N = Integer.parseInt(br.readLine());
        M = Integer.parseInt(br.readLine());
        D = new long[N+1][N+1];
        //N의 크기가 최대 100이므로 시간 복잡도의 최대는 1000000. N이 너무 크면 플로이드 와샬을 적용할 수 없다.

        for(int i=1; i<=N; i++) {
            for(int j=1; j<=N; j++) {
                if(i == j) D[i][j] = 0;
                else D[i][j] = Integer.MAX_VALUE;
            }
        }

        for(int i=1; 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());

            D[start][end] = Math.min(D[start][end], cost);
        }

        floyd();

        for(int i=1; i<=N; i++) {
            for(int j=1; j<=N; j++) {
                long num = (D[i][j] == Integer.MAX_VALUE) ? 0 : D[i][j];
                bw.write(num+ " ");
            }
            bw.write("\n");
        }

        br.close();
        bw.flush();
        bw.close();
    }

    private static void floyd() {
        /*
        전체의 최단경로는 부분 경로들 역시 최단 경로여야 한다.
        S에서 출발해 바로 E로 오는 거리와 S에서 출발해 K를 거쳐 E로 오는 거리 중 더 짧은 것이 최단경로가 된다.
         */
        //경유지 K
        //출발노드
        //도착노드 순으로 3중 for문
        for(int k=1; k<=N; k++) {
            for(int s=1; s<=N; s++) {
                for(int e=1; e<=N; e++) {
                    D[s][e] = Math.min(D[s][e], D[k][e]+D[s][k]); //
                }
            }
        }
    }
}