public class Main {
    public static int INF = 1_000_000_000;

    public static void floydWarshall(int v, int e, int[][] data, int start) {
        int[][] dist = new int[v + 1][v + 1];

        for (int i = 1; i < v + 1; i++) {
            for (int j = 1; j < v + 1; j++) {
                if (i != j) {
                    dist[i][j] = INF;
                }
            }
        }

        for (int i = 0; i < data.length; i++) {
            dist[data[i][0]][data[i][1]] = data[i][2];
        }

        /**
         * 틀린 코드 주의 -> 경유지 k에 대해서 k가 가장 안쪽 루프에 위치하면, i와 j에 대해 이미 선택된 경로가 경유지를 거치지 않고 직접 경로로 결정될 수 있음
         */
//        for (int i = 1; i < v + 1; i++) {
//            for (int j = 1; j < v + 1; j++) {
//                for (int k = 1; k < v + 1; k++) {
//                    if (dist[i][j] != INF && dist[j][k] != INF) {
//                        dist[i][k] = Math.min(dist[i][k], dist[i][j] + dist[j][k]);
//                    }
//                }
//            }
//        }

        // 경유지 k를 거치는 경우에 대해서 봐야함 주의
        for (int k = 1; k < v + 1; k++) {
            // i -> j (k를 거쳐서 가는 경우가 짧을 때 업데이트)
            for (int i = 1; i < v + 1; i++) {
                for (int j = 1; j < v + 1; j++) {
                    if (dist[i][k] != INF && dist[k][j] != INF) {
                        dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]);
                    }
                }
            }
        }

        for (int i = 1; i < dist.length; i++) {
            for (int j = 1; j < dist[1].length; j++) {
                if (dist[i][j] == INF) {
                    System.out.printf("%5s", "INF");
                } else {
                    System.out.printf("%5d", dist[i][j]);
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        // Test code
        int[][] data = {{1, 2, 8}, {1, 3, 6}, {1, 5, 5}, {2, 3, -5}, {2, 4, 1}, {2, 6, 4}, {3, 4, 4}, {4, 7, 3}, {5, 6, 5}, {6, 2, 0}, {6, 7, -7}};
        floydWarshall(7, 11, data, 1);
        System.out.println();

        data = new int[][]{{1, 2, 8}, {1, 3, 6}, {1, 5, 5}, {2, 3, -5}, {2, 4, 1}, {2, 6, 4}, {3, 4, 4}, {4, 7, 3}, {5, 6, 5}, {6, 2, -5}, {6, 7, -7}};
        floydWarshall(7, 11, data, 1);
    }
}