코테/백준

[백준/JAVA] 1854번: K번째 최단경로 찾기

imname1am 2023. 5. 2. 14:00
반응형

🔺 문제

 

1854번: K번째 최단경로 찾기

첫째 줄에 n, m, k가 주어진다. (1 ≤ n ≤ 1000, 0 ≤ m ≤ 2000000, 1 ≤ k ≤ 100) n과 m은 각각 김 조교가 여행을 고려하고 있는 도시들의 개수와, 도시 간에 존재하는 도로의 수이다. 이어지는 m개의 줄에

www.acmicpc.net

 

🔺 코드

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
import java.util.*;
import java.io.*;
 
public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine()," ");
        
        int N = Integer.parseInt(st.nextToken());   // 도시 개수
        int M = Integer.parseInt(st.nextToken());   // 간선 수
        int K = Integer.parseInt(st.nextToken());   // 몇 번째 최단 경로인지
        
        // 정렬 기준 설정 (내림차순)
        Comparator<Integer> cp = new Comparator<>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 < o2 ? 1 : -1;
            }
        };
        
        // 최단 거리 큐 배열 초기화
        PriorityQueue<Integer>[] distQ = new PriorityQueue[N + 1];
        for(int i = 0 ; i <= N ; i++) {
            distQ[i] = new PriorityQueue<Integer>(K, cp);
        }
        
        // 인접 행렬에 그래프 데이터 저장
        int[][] W = new int[1001][1001];
        while(M --> 0) {
            st = new StringTokenizer(br.readLine()," ");
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            
            W[a][b] = c;
        }
        
        
        // 다익스트라 수행
        PriorityQueue<Node> pq = new PriorityQueue<>();
        pq.add(new Node(10));
        distQ[1].add(0);
        
        while(!pq.isEmpty()) {
            Node u = pq.poll();
            
            for(int adjNode = 1 ; adjNode <= N ; adjNode++) {
                // 연결된 모든 노드로 검색
                if(W[u.node][adjNode] != 0) {
                    
                    // 저장된 경로가 K가 안 되면 그냥 추가
                    if(distQ[adjNode].size() < K) {
                        distQ[adjNode].add( u.cost + W[u.node][adjNode] );
                        pq.add(new Node(adjNode, u.cost + W[u.node][adjNode]));
                    }
                    
                    // 저장된 경로가 K개이고, 현재 가장 큰 값보다 작을 때만 추가
                    else if(distQ[adjNode].peek() > u.cost + W[u.node][adjNode]) {
                        distQ[adjNode].poll();                                  // 기존 큐에서 Max값(=마지막값) 먼저 삭제
                        distQ[adjNode].add( u.cost + W[u.node][adjNode] );      // 신규값 업데이트
                        pq.add(new Node(adjNode, u.cost + W[u.node][adjNode])); // 큐에 선택 노드 추가
                    }
                }
            }
        }
        
        
        // K번째 경로 출력
        StringBuilder sb = new StringBuilder();
        for(int i = 1 ; i <= N ; i++) {
            if(distQ[i].size() == K) sb.append(distQ[i].peek()).append("\n");
            else                     sb.append(-1).append("\n");
        }
        System.out.println(sb);
    }
}
 
// 노드 클래스 작성
class Node implements Comparable<Node>{
    int node;
    int cost;
    
    Node(int node, int cost) {
        this.node = node;
        this.cost = cost;
    }
    
    @Override
    public int compareTo(Node n) {
        return this.cost - n.cost;
    }
}
cs
✅ 해결 아이디어
✔ 다익스트라
- 최단 경로 배열, 각각 하나의 크기가 K인 우선순위 큐 배열로 선언

 

💥 유의사항

⇨ 우선선위 큐 배열 선언 방법

PrirorityQueue<Integer>[] distQ = new PriorityQueue[N + 1];

  → 우선순위 큐의 크기 & 정렬 기준 위한 코드 작성 필요

 

 

최단 거리 배열 채우기 규칙

1) 현재 노드에 저장된 경로 수 < K 일 때, 신규 경로 추가
2) 경로 == K일 때, 현재 경로 중 최대 경로 > 신규 경로일 때 업데이트
3) 사용한 노드는 방문 배열에 확인해 두고, 재사용하지 않는 부분은 삭제.
  •  

 


🔺 다른 풀이들

- 가장 깔끔 & 인접 리스트 , 향상형 for문 사용하심

 

[백준] 1854 K번째 최단경로 찾기

www.acmicpc.net/problem/1854 1854번: K번째 최단경로 찾기 첫째 줄에 n, m, k가 주어진다. (1 ≤ n ≤ 1000, 0 ≤ m ≤ 2000000, 1 ≤ k ≤ 100) n과 m은 각각 김 조교가 여행을 고려하고 있는 도시들의 개수와, 도시

void2017.tistory.com

 

- 인접 행렬/리스트 사용을 안 하심...

 

[백준 1854 : JAVA] K번째 최단경로 찾기 / 다익스트라

문제 풀이 다익스트라 알고리즘 응용 문제다. 일반적으로 다익스트라에서 다른 모든 노드로의 최단경로 비용을 저장하기 위해 int형 1차원 배열을 사용하는데 반해, 우선순위 큐 타입의 1차원 배

pangtrue.tistory.com

 

 

 

[백준] 1854 : K번째 최단경로 찾기 - JAVA

🙋🏻‍♀️다익스트라 알고리즘 사용!다른건 괜찮은데, k번째 최단경로를 어떻게 구할지가 큰 의문이었다.도저히 생각나지않아 해설을 보고 공부했다.최단 경로를 표현하는 배열을 우선순위

velog.io

 

 

- 도시별 최단거리 경로 배열 정렬할 때, Comparator 사용 안 하고
 costList[n] = newPriorityQueue<>(Collections.reverseOrder());로 한 줄 처리

 

백준 1854 K번째 최단경로

BOJ 1854 K번째 최단경로 풀이: 1. 도로가 단방향. 2. 시작점은 경로비용 0 (문제에서 제시) 3. 시작점은 1번도시로 고정 이 전제하에 각 도시에 대해 모든 최단경로를 가장 작은 순으로 정렬했을 때

noteofdeveloper.tistory.com

 

 

[자바] 백준 1854 - K번째 최단경로 찾기

문제 : boj1854 다익스트라에 대한 이해를 높히고 으용하는데 매우 도움되는 문제이다. 강추! (플로이드 와샬 이해에는 23258번 밤편지 강추) 다른 문제 풀다가 2번째 최단경로를 찾아야 하는 경우가

nahwasa.com

 

 

- 과정 설명이 복습용으로 굿

 

백준 1854번 - K번째 최단경로 찾기

https://www.acmicpc.net/problem/1854 1854번: K번째 최단경로 찾기 첫째 줄에 n, m, k가 주어진다. (1 ≤ n ≤ 1000, 0 ≤ m ≤ 2000000, 1 ≤ k ≤ 100) n과 m은 각각 김 조교가 여행을 고려하고 있는 도시들의 개수와,

goodbyeanma.tistory.com


💬 느낀 점

이야....

 

 

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

(참고)

✔ 우선순위 큐 정렬 기준 만들기

 

[자바/java] 우선순위 큐 정렬하기 priorityQueue sort

Heap 구조에 대해서는 tosuccess.tistory.com/31?category=853902 를 참고해주세요! 우선순위 큐는 힙(Heap)구조를 가지며, 정렬 기준에 따라 가장 큰 값이 먼저 나오는 MaxHeap을 만들 수 있고, 가장 작은 값이 나

tosuccess.tistory.com

 

 

[JAVA] 우선순위 큐 (Priority Queue), 정렬 전략 설정법

우선순위 큐 란? 큐 자료구조는 선입선출(FIFO) 방식이지만 우선순위 큐는 들어간 순서와는 상관없이 높은 우선순위를 가진 원소가 먼저나온다는 특징을 가짐 숫자가 작을수록 먼저 나오는 큐를

chb2005.tistory.com

 

반응형