BOJ 11779 최소비용 구하기 2

Tak Jeon·2024년 12월 17일

알고리즘

목록 보기
30/101

문제

n(1≤n≤1,000)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1≤m≤100,000)개의 버스가 있다. 우리는 A번째 도시에서 B번째 도시까지 가는데 드는 버스 비용을 최소화 시키려고 한다. 그러면 A번째 도시에서 B번째 도시 까지 가는데 드는 최소비용과 경로를 출력하여라. 항상 시작점에서 도착점으로의 경로가 존재한다.

입력

첫째 줄에 도시의 개수 n(1≤n≤1,000)이 주어지고 둘째 줄에는 버스의 개수 m(1≤m≤100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 그리고 그 다음에는 도착지의 도시 번호가 주어지고 또 그 버스 비용이 주어진다. 버스 비용은 0보다 크거나 같고, 100,000보다 작은 정수이다.

그리고 m+3째 줄에는 우리가 구하고자 하는 구간 출발점의 도시번호와 도착점의 도시번호가 주어진다.

출력

첫째 줄에 출발 도시에서 도착 도시까지 가는데 드는 최소 비용을 출력한다.

둘째 줄에는 그러한 최소 비용을 갖는 경로에 포함되어있는 도시의 개수를 출력한다. 출발 도시와 도착 도시도 포함한다.

셋째 줄에는 최소 비용을 갖는 경로를 방문하는 도시 순서대로 출력한다. 경로가 여러가지인 경우 아무거나 하나 출력한다.


문제 분석

  1. 정보

    • N개의 도시
    • M개의 버스
      • 버스는 출발 도시의 번호, 도착 도시의 번호, 버스 비용이 주어짐
  2. 목표

    • A도시에서 출발하여 B도시로 가는데 필요한 최소비용
    • 가는데 필요한 도시의 개수
    • 가는 경로를 차례대로 출력
  3. 제약 조건

    • N : 1N10001 \le N \le 1000
    • M : 1M1000001 \le M \le 100000

풀이

  1. 알고리즘

    • DFS 사용하여 비용을 기준으로 적은 도시부터 차례대로 계산
      • Node class 생성 : 도시 번호, 비용 저장
      • dist[] 배열 사용 : 해당 도시까지 가는데 필요한 최소 비용 저장
  2. 탐색 과정

    • DFS

      • Node class 생성 : 도시 번호, 비용 저장
      • dist[] 배열 생성 : 해당 도시까지 가는데 필요한 최소 비용 저장 위함.
      • ArrayList[] 배열 생성해 각 도시에서 탈 수 있는 버스와 해당 버스의 비용을 저장
      • 위 배열을 사용해 시작지점에서 DFS 알고리즘 실행
      • 만약 아직 방문하지 않았고, 다음 목적지까지의 최소비용(dist[다음])이 현재 목적지까지의 최소 비용(dist[현재]) + 다음 목적지까지 가는데 필요한 비용(cost)보다 크다면, 값 업데이트하고 큐에 추가
      • 추가로, path[] 배열을 생성해 path[다음 도시] = 현재 도시 값을 저장
    • 결과 생성

      • 경로 결과값 저장하기 위한 ArrayList 생성
      • 해당 ArrayList에 도착 지점 부터 차례대로 값을 저장
        • 값 저장 이후에는 해당 값을 path[현재 값]으로 업데이트 해주어 경로 생성
        • 시작 지점까지 경로가 생성되면, 해당 값 reverse 하여 시작 -> 도착 지점까지의 경로 생성
      • dist[도착], ArrayList 크기, 해당 경로를 차례대로 출력

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class BOJ11779 {

    static class Node implements Comparable<Node>{
        int city;
        int cost;

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

        @Override
        public int compareTo(Node o) {
            return this.cost - o.cost;
        }
    }

    static int N, M;
    static ArrayList<Node>[] list;
    static int[] path, dist;

    private static void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        M = Integer.parseInt(br.readLine());
        list = new ArrayList[N + 1];
        path = new int[N + 1];
        dist = new int[N + 1];
        for (int i = 1; i <= N; i++) {
            list[i] = new ArrayList<>();
            path[i] = i;
        }

        StringTokenizer st;
        for (int i = 0; i < M; i++) {
            st = new StringTokenizer(br.readLine());
            int s = Integer.parseInt(st.nextToken());
            int e = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            list[s].add(new Node(e, c));
        }

        st = new StringTokenizer(br.readLine());
        int s = Integer.parseInt(st.nextToken());
        int e = Integer.parseInt(st.nextToken());

        DFS(s, e);

        System.out.println(dist[e]);
        ArrayList<Integer> resultPath = new ArrayList<>();
        int cur = e;
        while (cur != s) {
            resultPath.add(cur);
            cur = path[cur];
        }
        resultPath.add(cur);
        Collections.reverse(resultPath);
        System.out.println(resultPath.size());
        for (Integer i : resultPath) {
            System.out.print(i + " ");
        }
    }

    static void DFS(int s, int e) {
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(s, 0));
        boolean[] visited = new boolean[N + 1];
        Arrays.fill(dist, Integer.MAX_VALUE);
        dist[s] = 0;

        while (!pq.isEmpty()) {
            Node cur = pq.poll();

            if (cur.city == e) {
                return;
            }

            if(visited[cur.city]) continue;
            visited[cur.city] = true;

            for (Node next : list[cur.city]) {
                if (!visited[next.city] && dist[next.city] > dist[cur.city] + next.cost) {
                    dist[next.city] = dist[cur.city] + next.cost;
                    path[next.city] = cur.city;
                    pq.add(new Node(next.city, dist[next.city]));
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        BOJ11779.solution();
    }
}

profile
문제 해결을 좋아하는 개발자 입니다 :)

0개의 댓글