-
1939번 - 중량제한알고리즘/백준 2023. 7. 15. 10:44
1️⃣ 최대 힙(우선순위 큐), Greedy
✏️ 풀이 과정
섬과 다리라는 컨셉으로부터 그래프 관련 문제임을 유추할 수 있습니다. 문제에서 요구하는 사항은 조금 특이한데 최단 거리나 최장 거리가 아니라 시작점에서 끝점으로 가는 최장 경로(원래 거리가 아니라 무게인데 편의상 거리처럼 표현하겠습니다.)에서 가중치의 최솟값을 구해야 합니다.(사실 저 최솟값을 가장 크게 만드는 경로가 최장 경로라는 걸 알았다면 문제가 해결된 것이나 마찬가지입니다.)
이를 구현할 수 있는 방법은 굉장히 많은데 Greedy, Pruning, Kruskal, Dijkstra, Dynamic Programing, 이분탐색 등의 방법으로 문제를 해결할 수 있습니다. 여기서는 최대 힙(우선순위 큐)를 통해 Greedy Algorithm으로 항상 더 큰 가중치를 선택하다가 목표점에 도달하면 종료하는 방법으로 가장 높은 가중치들만 갖는 경로를 구현합니다.
구현은 BFS와 비슷한 방법으로 하지만 최대 힙을 이용하기 때문에 결과적으로 다익스트라 알고리즘과 비슷해집니다. 종착점에 도착했을 때 종료하기 때문에 더 빠르게 끝낼 수 있습니다. while문 안에서는 현재 가중치가 지금까지 나온 최솟값보다 작으면 업데이트하고 종착점에 도착하면 break, 이외의 경우에는 연결된 정점들을 모두 최대 힙에 넣습니다.
break 이후 현재까지 업데이트된 최솟값을 출력하면 문제가 해결됩니다.
⏱ 시간 복잡도
while문에서 break가 일어나지 않으면 모든 간선을 힙에 넣기 때문에 O(ElogV)가 됩니다.(힙에 add나 remove를 할 때 O(logV)이므로
💻 코드
JavaScript
const input = require("fs") .readFileSync(process.platform === "linux" ? "/dev/stdin" : "input.txt") .toString() .trim() .split("\n"); const swap = (arr, a, b) => { const tmp = arr[a]; arr[a] = arr[b]; arr[b] = tmp; }; class MaxHeap { constructor() { this.heap = []; this.cnt = 0; } isEmpty() { if (this.cnt === 0) { return true; } else { return false; } } add(item) { this.heap[++this.cnt] = item; let idx = this.cnt; while (idx > 1) { if (this.heap[parseInt(idx / 2)].w < this.heap[idx].w) { swap(this.heap, parseInt(idx / 2), idx); idx = parseInt(idx / 2); } else { break; } } } remove() { if (this.cnt === 0) { return 0; } const res = this.heap[1]; this.heap[1] = this.heap[this.cnt--]; let idx = 1; while (2 * idx <= this.cnt) { if (2 * idx == this.cnt) { if (this.heap[2 * idx].w > this.heap[idx].w) swap(this.heap, idx, 2 * idx); break; } else { if (this.heap[2 * idx + 1].w > this.heap[2 * idx].w) { if (this.heap[2 * idx + 1].w > this.heap[idx].w) { swap(this.heap, idx, 2 * idx + 1); idx = 2 * idx + 1; } else { break; } } else { if (this.heap[2 * idx].w > this.heap[idx].w) { swap(this.heap, idx, 2 * idx); idx = 2 * idx; } else { break; } } } } return res; } } class Node { constructor(v, w, link) { this.v = v; this.w = w; this.link = link; } } const [N, M] = input[0].split(" ").map(Number); const adjList = []; let from, to, w; for (let i = 1; i <= M; i++) { [from, to, w] = input[i].split(" ").map(Number); adjList[from] = new Node(to, w, adjList[from]); adjList[to] = new Node(from, w, adjList[to]); } const hp = new MaxHeap(); const INF = 1000000001; let min = INF; const [start, end] = input[M + 1].split(" ").map(Number); hp.add(new Node(start, INF, null)); let cur; visited = []; visited[start] = true; while (!hp.isEmpty()) { cur = hp.remove(); visited[cur.v] = true; if (cur.w < min) { min = cur.w; } if (cur.v === end) { break; } for (let n = adjList[cur.v]; n != null; n = n.link) { if (!visited[n.v]) { hp.add(n); } } } console.log(min);
'알고리즘 > 백준' 카테고리의 다른 글
1865번 - 웜홀 (0) 2023.07.16 11657번 - 타임머신 (0) 2023.07.16 17144번 - 미세먼지 안녕! (0) 2023.07.15 17276번 - 배열 돌리기 (0) 2023.07.13 1504번 - 특정한 최단 경로 (0) 2023.07.09