Reference BOJ | 최단 경로
1번 노드에 출발했을 때 그 외 노드에 방문할 수 있는 최단 경로를 구하는 문제이다.
초기 배열에는 자바스크립트 Infinity 값을 설정해준다. 배열을 그냥 편하게 dist
라고 부르고자 한다면 dist[i] 는 1에서 i까지 갈 수 있는 최단 경로다. 따라서 dist[1]=0으로 초기화 시켜준다.
1에서 나아가는 경로를 체크한다.
2 ( 경로 구하는 경우 = dist[1] + 12 )가 dist[2] 보다 작다면 값을 교체해준다. 3( 경로 구하는 경우 = dist[1] + 4 ) 또한 마찬가지로 현재 경로가 기존 dist[3]보다 작다면 교체해준다.
1 (checked) 된 곳을 제외하고 2 ~ 6에서 가장 minimum한 값을 찾는다. 1에서 나아간 뒤 체크한다면 3이 checked 되는 것이다.
Minimum한 값을 찾을 때 배열을 순회하는 것은 O(N)이 걸리지만 최소 heap은 O(logN)이 걸리기 때문에 찾기 위해서는 최소 heap를 사용하는 것이 좋다
1에서 나아간 방향의 값을 찾았듯, checked 된 3에서 나아간 방향을 찾는다.
다익스트라를 이용할 때 그래프의 가중치는 반드시 양수여야 한다.
가중치가 음수인 경우는 벨만-포드 알고리즘을 이용해야 한다.
class MinHeap {
constructor() {
this.nodes = [];
}
insert(value) {
this.nodes.push(value);
this.upheap();
}
upheap() {
let index = this.nodes.length - 1;
let node = this.nodes[index];
let parentNodeIndex = Math.floor((index - 1) / 2);
while (index > 0 && node[1] < this.nodes[parentNodeIndex][1]) {
this.nodes[index] = this.nodes[parentNodeIndex];
index = parentNodeIndex;
parentNodeIndex = Math.floor((index - 1) / 2);
}
this.nodes[index] = node;
}
downheap() {
let index = 0;
let node = this.nodes[index];
while (index <= Math.floor((this.size() - 1) / 2)) {
let childNodeIndex = index * 2 + 1;
if (
childNodeIndex < this.size() &&
this.nodes[childNodeIndex + 1] &&
this.nodes[childNodeIndex][1] > this.nodes[childNodeIndex + 1][1]
) {
childNodeIndex += 1;
}
if (
!this.nodes[childNodeIndex] ||
node[1] <= this.nodes[childNodeIndex][1]
) {
break;
}
this.nodes[index] = this.nodes[childNodeIndex];
index = childNodeIndex;
}
this.nodes[index] = node;
}
get() {
if (this.size() === 1) {
return this.nodes.pop();
}
const node = this.nodes[0];
this.nodes[0] = this.nodes.pop();
this.downheap();
return node;
}
size() {
return this.nodes.length;
}
}
한 정점에서 모든 정점으로 가는 최단 경로를 구하는 다익스트라에 비해 플로이드 와샬은 모든 정점에서 모든 정점으로 가는 최단 경로를 구한다.
Reference BOJ | 2660 회장 뽑기
dist 라는 이차원 배열을 만들어 준다.
for(let i=1;i<=n;i++){
for(let j=1;j<=n;j++){
for(let k=1;k<=n;k++){
dist[j][k]=Math.min(dist[j][k], dist[j][i]+dist[i][k];
}
}
}
플로이드 와샬은 위의 3중 for문만 기억해주면 된다.
dist[i][j]는 i에서 j까지 가는 최단거리를 의미한다.
개인적으로 플로이드 와샬을 사용하기 보다는 다익스트라로 간선마다 체크하는데 어떤 방식으로든 시간 차이가 많이 나지 않는 것 같다.. (?)