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

 

1238번: 파티

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 10,000), X가 공백으로 구분되어 입력된다. 두 번째 줄부터 M+1번째 줄까지 i번째 도로의 시작점, 끝점, 그리고 이 도로를 지나는데 필요한 소요시간 Ti가 들어

www.acmicpc.net

다익스트라 알고리즘으로 접근한 문제다. 힙 구현이 필요하다. 직접 구현할 역량이 안되기에, Rhyno님이 작성한 힙을 사용하였다.

 

풀이

간선과 가중치를 입력받은 map 배열을 통해, 다익스트라 알고리즘을 사용한다. 양방향 간선이 아닌 단방향 간선이기에 우선 파티 장소 x에서 각 마을로 되돌아가는 배열을 생성, 다익스트라 알고리즘을 통해 각 인덱스에 저장. 이후 1 ~ n번 마을에서 x로 향하는 최단거리를 한 번 더 다익스트라 알고리즘을 통해 방금 저장한 배열에 추가시켜 준다. 마지막으로 배열에 담긴 최댓값을 출력한다.

 

정답 코드

import Foundation
//heap by rhyno
public struct Heap<T> {
var nodes: [T] = []
let comparer: (T,T) -> Bool
var isEmpty: Bool {
return nodes.isEmpty
}
init(comparer: @escaping (T,T) -> Bool) {
self.comparer = comparer
}
func peek() -> T? {
return nodes.first
}
mutating func insert(_ element: T) {
var index = nodes.count
nodes.append(element)
while index > 0, !comparer(nodes[index],nodes[(index-1)/2]) {
nodes.swapAt(index, (index-1)/2)
index = (index-1)/2
}
}
mutating func delete() -> T? {
guard !nodes.isEmpty else {
return nil
}
if nodes.count == 1 {
return nodes.removeFirst()
}
let result = nodes.first
nodes.swapAt(0, nodes.count-1)
_ = nodes.popLast()
var index = 0
while index < nodes.count {
let left = index * 2 + 1
let right = left + 1
if right < nodes.count {
if comparer(nodes[left], nodes[right]),
!comparer(nodes[right], nodes[index]) {
nodes.swapAt(right, index)
index = right
} else if !comparer(nodes[left], nodes[index]){
nodes.swapAt(left, index)
index = left
} else {
break
}
} else if left < nodes.count {
if !comparer(nodes[left], nodes[index]) {
nodes.swapAt(left, index)
index = left
} else {
break
}
} else {
break
}
}
return result
}
}
extension Heap where T: Comparable {
init() {
self.init(comparer: <)
}
}
let nmx = readLine()!.split(separator: " ").map{Int($0)!}
let n = nmx[0]
let m = nmx[1]
let x = nmx[2]-1
var map = Array(repeating: [(Int,Int)](), count: n)
for _ in 0..<m{
let info = readLine()!.split(separator: " ").map{Int($0)!}
let u = info[0]-1
let v = info[1]-1
let cost = info[2]
map[u].append((v,cost))
}
for i in 0..<n{
map[i].sort(by: { $0.1 < $1.1 })
}
func dij(from a:Int) -> [Int]{
var q = Heap<(Int,Int)>(comparer: { $0.1 > $1.1 })
var visited = Array(repeating: false, count: n)
var result = Array(repeating: -1, count: n)
result[a] = 0
q.insert((a,0))
while !q.isEmpty{
let curr = q.delete()!
let idx = curr.0
if !q.isEmpty && visited[idx]{ continue }
visited[idx] = true
for next in map[idx]{
if (result[next.0] == -1) || (result[next.0] > result[idx] + next.1){
result[next.0] = result[idx] + next.1
q.insert((next.0,result[next.0]))
}
}
}
return result
}
var ans = dij(from: x)
for i in 0..<n{
ans[i] += dij(from: i)[x]
}
print(ans.max()!)
view raw 1238.swift hosted with ❤ by GitHub

'Problem Solving > BOJ' 카테고리의 다른 글

[2018] 수들의 합 5  (0) 2023.01.11
[1504] 특정한 최단 경로  (0) 2023.01.04
[2056] 작업  (0) 2023.01.02
[14567] 선수과목  (0) 2023.01.01
[1584] 게임  (0) 2022.12.30

+ Recent posts