Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions WEEK11/백준_1753_최단경로/JSON.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
let ve = readLine()!.split(separator: " ").compactMap { Int($0) }
let (v, e) = (ve[0], ve[1])
let k = Int(readLine()!)!
var graph = [[(w: Int, v: Int)]](repeating: [], count: v + 1)

for _ in 0..<e {
let input = readLine()!.split(separator: " ").compactMap { Int($0) }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

readLine()split을 이용한 입력 방식은 간선 수가 많은 경우(최대 300,000개) 시간 초과를 유발할 수 있습니다. 백준의 골드 등급 이상 문제에서는 FileIO와 같은 더 빠른 입력 방식을 사용하는 것이 안전합니다.

graph[input[0]].append((input[2], input[1]))
}

var dists = [Int](repeating: Int.max, count: v + 1)
var heap = Heap<(w: Int, v: Int)> { $0.w < $1.w }
heap.push((0, k))
dists[k] = 0

while let (curDist, curValue) = heap.pop() {
guard dists[curValue] == curDist else { continue }

for (nextWeight, nextValue) in graph[curValue] {
let nextDist = curDist + nextWeight
if nextDist < dists[nextValue] {
heap.push((nextDist, nextValue))
dists[nextValue] = nextDist
}
}
}

for i in 1...v {
let dist = dists[i]
print(dist == Int.max ? "INF" : dist)
}
Comment on lines +28 to +31
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

반복문 내에서 print를 매번 호출하는 것은 출력 성능에 좋지 않습니다. 결과를 하나의 문자열로 모아서 한 번에 출력하는 것이 효율적입니다.

Suggested change
for i in 1...v {
let dist = dists[i]
print(dist == Int.max ? "INF" : dist)
}
print((1...v).map { i in
let dist = dists[i]
return dist == Int.max ? "INF" : "\(dist)"
}.joined(separator: "\n"))


struct Heap<T> {
var elements: [T]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

elements 배열을 선언과 동시에 빈 배열로 초기화하여 코드의 의도를 명확히 하고 생성자를 간소화할 수 있습니다.

Suggested change
var elements: [T]
var elements: [T] = []

let priority: (T, T) -> Bool

var isEmpty: Bool { elements.isEmpty }
var count: Int { elements.count }

init(_ priority: @escaping (T, T) -> Bool) {
self.elements = []
self.priority = priority
}
Comment on lines +40 to +43
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

elements가 선언부에서 이미 초기화되어 있다면 생성자에서 중복으로 할당할 필요가 없습니다.

    init(_ priority: @escaping (T, T) -> Bool) {
        self.priority = priority
    }


mutating func push(_ element: T) {
elements.append(element)
siftUp(from: elements.count - 1)
}

mutating func pop() -> T? {
guard !elements.isEmpty else { return nil }
elements.swapAt(0, elements.count - 1)
let removed = elements.removeLast()
siftDown(from: 0)
return removed
}

private mutating func siftUp(from index: Int) {
var newIndex = index
var parent = (index - 1) / 2

while newIndex > 0 && priority(elements[newIndex], elements[parent]) {
elements.swapAt(newIndex, parent)
newIndex = parent
parent = (newIndex - 1) / 2
}
}

private mutating func siftDown(from index: Int) {
var parent = index

while true {
let left = parent * 2 + 1
let right = parent * 2 + 2
var candidate = parent

if left < elements.count && priority(elements[left], elements[parent]) {
candidate = left
}
if right < elements.count && priority(elements[right], elements[candidate]) {
candidate = right
}

guard candidate != parent else { break }
elements.swapAt(candidate, parent)
parent = candidate
}
}
}