백준 1504번 JAVA : 특정한 최단 경로

문제

백준 문제 링크 : https://www.acmicpc.net/problem/1504

풀이전략

최단거리이기 때문에 다익스트라 알고리즘을 사용한다. 하지만 문제에서 주어지는 2가지 정점을 지나야 한다는 요구사항이 있다. 반드시 지나야하는 두 정점을 v1, v2 라고 하면 경로는 다음과같이 구할 수 있다.

  1. 1 -> v1 -> v2 -> N
  2. 1 -> v2 -> v1 -> N

따라서 1번 경로를 해결하려면 다익스트라 알고리즘을 1-> v1으로 한번, v1-> v2로 한번, v2 -> N 으로 한번 총 3번 돌리면 된다. 2번경로도 마찬가지이다.

코드

package backjoon.P1504;

import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.PriorityQueue; import java.util.StringTokenizer;

public class Main {

static class Node{
    int v, dis;

    public Node(int v, int dis) {
        this.v = v;
        this.dis = dis;
    }
}

static int[] distance;
static int INF = 200000000;
static  ArrayList<ArrayList<Node>> graph;
public static void main(String[] args) throws Exception {
    System.setIn(new FileInputStream("src/backjoon/input.txt"));
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    StringTokenizer st;
    st = new StringTokenizer(br.readLine());
    int N = Integer.parseInt(st.nextToken());
    int E = Integer.parseInt(st.nextToken());

    graph = new ArrayList<>();

    for(int i=0; i<=N; i++){
        graph.add(new ArrayList<>());
    }

    for(int i=0; i<E; i++){
        st = new StringTokenizer(br.readLine());
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        int c = Integer.parseInt(st.nextToken());

        graph.get(a).add(new Node(b, c));
        graph.get(b).add(new Node(a, c));

    }



    st = new StringTokenizer(br.readLine());
    int v1 = Integer.parseInt(st.nextToken());
    int v2 = Integer.parseInt(st.nextToken());

    distance = new int[N+1];

    // 1 -> v1 -> v2 -> N
    int res1 = 0;
    res1 += dijkstra(1, v1);
    res1 += dijkstra(v1, v2);
    res1 += dijkstra(v2, N);



    // 1 -> v2 -> v1 -> N
    int res2 = 0;
    res2 += dijkstra(1, v2);
    res2 += dijkstra(v2, v1);
    res2 += dijkstra(v1, N);
    int answer = (res1 >= INF && res2 >= INF)? -1 : Math.min(res1, res2);
    System.out.println(answer);
}


public static int dijkstra(int start, int end){
    PriorityQueue<Node> pq = new PriorityQueue<>((n1, n2) -> {
        return n1.dis - n2.dis;
    });

    Arrays.fill(distance, INF);

    distance[start] = 0;
    pq.add(new Node(start, 0));

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

        if(distance[cur.v] < cur.dis) continue;

        for(Node node : graph.get(cur.v)){

            if(distance[cur.v] + node.dis < distance[node.v] ){

                distance[node.v] = distance[cur.v] + node.dis;
                pq.add(new Node(node.v, distance[cur.v] + node.dis));
            }
        }

    }

    return distance[end];
}

}

회고

  • 반드시 지나야 하는 두 정점을 정해주었기 때문에 더 편하게 풀었다. 처음에 문제를 접근할 때 반드시 지나야 하는 두 정점을 주어지는줄 몰랐다. 문제를 상세히 읽는게 중요하다.

Written by@Gomster
항상 노력하고 나아가는 백엔드 개발자가 되고 싶은 대학생입니다.

GitHub