코테/백준

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

imname1am 2024. 5. 15. 17:25
반응형

📖 문제

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

 

 

 

💡  풀이 방식

• 다익스트라

필요 자료구조
- 인접 배열 리스트
- 시작점에서 각 정점까지 가는 최단 거리 저장용 int형 배열
- N개의 각 정점에 대한 boolean형 방문 표시 배열
- (목적지, 거리) 정보를 저장하는 객체

 

 

1. E개의 입력을 받으며 두 정점 간 거리 정보를 양방향으로 저장한다.

2. 꼭 지나쳐야 하는 두 정점 v1, v2를 입력받는다.

3. ① 경로 1 > v1 > v2 > N을 지날 때의 최단 거리와, ② 경로 1 > v2 > v1 > N을 지날 때의 최단거리를 계산한다. (다익스트라)

4. 두 최단 거리가 모두 최댓값인 INF보다 크거나 같으면, 경로가 없는 것이므로 -1을 출력하고, 그게 아니라면 경로 1의 최단 거리와 경로 2의 최단 경로 길이 중 최솟값을 정답으로 출력한다.

 

 

 

 

💥 유의사항

최단 거리 배열 dist를 채우는 초기값은 20,000,000 (= 간선의 갯수 E의 최댓값 20만 * 두 정점 간 최대 거리 1000)으로 설정한다.

Integer.MAX_VALUE로 했다간 오버플로우가 발생할 수 있다.

 

 

 

🔺 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import java.util.*;
import java.io.*;
 
public class Main {
    static int INF = 200000*100;    // 간선 최대 개수 E * 가중치 최댓값 c
    
    static int N,E;
    static List<Node>[] list;
    static int[] dist;  // 시작점에서 각 정점으로 가는 최단 거리
    static boolean[] visited;   // 방문 표시 배열
    
    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());
        E = Integer.parseInt(st.nextToken());
        
        list = new ArrayList[N+1];
        for(int i = 1 ; i <= N ; i++)   list[i] = new ArrayList<>();
        
        dist = new int[N+1];
        visited = new boolean[N+1];
        
        while(E --> 0) {
            st = new StringTokenizer(br.readLine(), " ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
 
            // 양방향
            list[a].add(new Node(b,c));
            list[b].add(new Node(a,c));
        }
        
        st = new StringTokenizer(br.readLine(), " ");
        int v1 = Integer.parseInt(st.nextToken());
        int v2 = Integer.parseInt(st.nextToken());
        
        // 경로1) 1 > v1 > v2 > N
        int ans1 = 0;
        ans1 += dijkstra(1, v1);
        ans1 += dijkstra(v1, v2);
        ans1 += dijkstra(v2, N);
        
        // 경로2) 1 > v2 > v1 > N
        int ans2 = 0;
        ans2 += dijkstra(1, v2);
        ans2 += dijkstra(v2, v1);
        ans2 += dijkstra(v1, N);
        
        int answer = 0;
        answer = (ans1 >= INF && ans2 >= INF) ? -1 : Math.min(ans1, ans2);
        System.out.println(answer);
    }
    
    // [다익스트라]
    private static int dijkstra(int start, int end) {
        // 방문 표시 배열과 거리 배열은 매번 초기화하기 !!
        Arrays.fill(visited, false);
        Arrays.fill(dist, INF);
        
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(start, 0));
        
        dist[start] = 0;    // 시작점 거리 0으로 세팅
        
        while(!pq.isEmpty()) {
            Node now = pq.poll();
            
            if(visited[now.e])  continue;   // 방문했던 정점은 pass
            visited[now.e] = true;
            
            // 현재 노드에 연결된 다른 노드 탐색
            for(Node next : list[now.e]) {
                if(dist[next.e] > now.v + next.v) { // 더 작은 경로로 이동
                    dist[next.e] = now.v + next.v;
                    pq.add(new Node(next.e, dist[next.e]));
                }
            }
        }
        
        return dist[end];   // 목적지 end까지의 최단 거리
    }
}
 
class Node implements Comparable<Node> {
    int e, v;   // 목적지, 거리
    
    public Node(int e, int v) {
        this.e = e;
        this.v = v;
    }
    
    // 거리 기준 오름차순 정렬
    @Override
    public int compareTo(Node n) {
        return this.v - n.v;
    }
}
cs

 

 

 

➕ 다른 풀이 방식

더 작은 경로로 이동하도록 갱신하는 코드 부분이 약간 다르다.

 

[다익스트라] 백준 1504번 특정한 최단 경로 - JAVA

오랜만에 다익스트라 푸니까 원리 다 까먹어버림 1. 출처 1504번: 특정한 최단 경로 첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄에 걸

tksgk2598.tistory.com

if(dist[next.e] > dist[now.e] + next.v) {
	dist[next.e] = dist[now.e] + next.v;
    pq.add(new Node(next.e, dist[next.e]));
}

 


💦 어려웠던 점

- 다익스트라를 잊고 있었다,,

- 그래도 우선순위 큐 쓸 생각은 들었다!

- 1>v1>v2>N으로 가는 경로와 1>v2>v1>N으로 가는 경로의 최단 길이를 구할 생각을 하지 못 했다.

 

🧐 새로 알게 된 내용

- 잊고 있던 다익스트라 상기시키기,,

 

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

 

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

백준 1504번 특정한 최단 경로 (JAVA) https://www.acmicpc.net/problem/1504 1504번: 특정한 최단 경로 첫째 줄에 정점의 개수 N과 간선의 개수 E가 주어진다. (2 ≤ N ≤ 800, 0 ≤ E ≤ 200,000) 둘째 줄부터 E개의 줄

lucysworld.tistory.com

 

 

[BOJ] 백준 1504번 : 특정한 최단 경로 (JAVA)

문제 방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶

steady-coding.tistory.com

 

반응형