알고리즘/최소신장트리(MST) & 다익스트라

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

K.두부 2022. 12. 8. 20:06
반응형

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

 

1504번: 특정한 최단 경로

첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸쳐서 세 개의 정수 a, b, c가 주어지는데, a번 정점에서 b번 정점까지 양방향 길이 존

www.acmicpc.net

풀이

전형적인 다익스트라 알고리즘 문제.

최단경로 응용 문제로 진행 과정을 자세하게 적어뒀다. 

 

다익스트라에 대해서 처음 접하시는 분은 아래 링크를 먼저 읽어보는 걸 추천한다.

https://sookr5416.tistory.com/160

 

자바 다익스트라(Dijkstra) 알고리즘 정의 및 작동 원리

다익스트라 알고리즘 (Dijkstra) 정의 음의 가중치가 없는 그래프의 한 노드에서 각 모든 노드까지의 최단거리를 구하는 알고리즘으로 BFS와 DP를 활용하는게 특징임 다익스트라 알고리즘 작동 원

sookr5416.tistory.com

다익스트라 알고리즘은 한 노드에서 모든 노드 사이의 최단거리를 구할 수 있는 알고리즘이다.

 

위 문제에서는 특정 노드 2개를 반드시 방문해야된다고 적혀있다.

복잡하게 생각할 것 없다. 다익스트라의 알고리즘을 쪼개서 경로를 찾아주면 된다.

 

<최종코드>

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

public class Main {
    static int N;
    static ArrayList<Node>[] arrList;
    public static class Node implements Comparable<Node> {
        int e;
        int v;
		
        public Node (int e, int v) {
            this.e = e;
            this.v = v;
        }
		
        public int compareTo (Node o) {
            return this.v - o.v;
        }
    }
	
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
		
        N = Integer.parseInt(st.nextToken());
        int E = Integer.parseInt(st.nextToken());
		
        arrList = new ArrayList[N+1];
        for (int i=1; i<=N; i++) {
            arrList[i] = new ArrayList<Node>();
        }
		
        for (int i=0; i<E; i++) {
            st = new StringTokenizer(br.readLine());
			
            int start = Integer.parseInt(st.nextToken());
            int end = Integer.parseInt(st.nextToken());
            int value = Integer.parseInt(st.nextToken());
			
            arrList[start].add(new Node(end, value));
            arrList[end].add(new Node(start, value));
        }
		
        st = new StringTokenizer(br.readLine());
        int v1 = Integer.parseInt(st.nextToken());
        int v2 = Integer.parseInt(st.nextToken());
		
        // 1번
        long first = 0;
        first += Dijkstra(1, v1);
        first += Dijkstra(v1, v2);
        first += Dijkstra(v2, N);
		
        // 2번
        long second = 0;
        second += Dijkstra(1, v2);
        second += Dijkstra(v2, v1);
        second += Dijkstra(v1, N);
		
        if (Math.min(first, second) >= 200000000) System.out.println(-1);
        else System.out.println(Math.min(first, second));
    }
	
    public static int Dijkstra(int start, int end) {
        int[] dp = new int[N+1];
        Arrays.fill(dp, 200000000); // 200,000(E의 최대값) * 1,000(c의 최대값) - overflow 방지
		
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(start, 0));
        dp[start] = 0;
		
        while (!pq.isEmpty()) {
            Node now = pq.poll();
			
            for (Node n : arrList[now.e]) {
                if (dp[n.e] > dp[now.e] + n.v) {
                    dp[n.e]= dp[now.e] + n.v;
                    pq.add(new Node(n.e, dp[n.e]));
                }
            }
        }
		
        return dp[end];
    }
}

 

반응형