문제 설명
그래프가 주어지고, 한 정점에서 다른 정점까지의 최단 경로를 찾는 알고리즘을 구현하시오.
주어진 그래프는 유향 그래프이며, 각 간선은 가중치를 가집니다.
정점은 0부터 N-1까지의 정수로 표현되며, 두 정점 간의 간선이 있을 경우 그 가중치를 알고 있습니다.
입력 형식:
- 첫째 줄에 정점의 개수 N (1 ≤ N ≤ 1000)이 주어진다.
- 둘째 줄에 간선의 개수 M (1 ≤ M ≤ 10000)이 주어진다.
- 셋째 줄부터 M개의 줄에 걸쳐 각 간선의 정보가 주어진다.
이는 “A B C”의 형태로, A에서 B로 가는 가중치 C인 간선이 있다는 의미이다.
(1 ≤ A, B ≤ N, 1 ≤ C ≤ 1000) - 마지막 줄에 시작점 S (1 ≤ S ≤ N)과 도착점 E가 주어진다.
문제 풀이 과정
다익스트라 알고리즘은 그래프에서 한 정점에서 다른 정점까지의 최단 경로를 찾는 알고리즘입니다.
이 알고리즘은 음의 가중치가 없는 경우에만 올바르게 작동하므로, 가중치가 0보다 크거나 같은지 확인하는 것이 중요합니다.
아래는 코틀린을 이용한 다익스트라 알고리즘의 구현 과정입니다.
1. 그래프 표현
그래프를 표현하기 위해 인접 리스트를 사용합니다.
각 정점에 대해 그 정점에서 도달할 수 있는 정점과 그 간선의 가중치를 저장합니다.
예를 들어, 정수 배열을 이용하여 각 정점을 리스트로 표현할 수 있습니다.
val graph = Array(N) { mutableListOf>() }
2. 입력 처리
입력 받은 간선 정보를 그래프에 추가합니다.
입력 형식에 따라서 반복문을 통해 각 간선의 정보를 저장합니다.
for (i in 0 until M) {
val (A, B, C) = readLine()!!.split(" ").map { it.toInt() }
graph[A-1].add(Pair(B-1, C)) // A에서 B로 가는 C 가중치
}
3. 다익스트라 알고리즘 구현
우선순위 큐를 이용하여 현재 최소 경로를 찾기 위한 알고리즘을 구현합니다.
다음은 다익스트라 알고리즘의 핵심 로직입니다.
fun dijkstra(start: Int) {
val distance = Array(N) { Int.MAX_VALUE }
distance[start] = 0
val pq = PriorityQueue>(compareBy { it.second })
pq.add(Pair(start, 0))
while (pq.isNotEmpty()) {
val (current, dist) = pq.poll()
if (dist > distance[current]) continue
for (next in graph[current]) {
val (nextNode, weight) = next
val newDist = dist + weight
if (newDist < distance[nextNode]) {
distance[nextNode] = newDist
pq.add(Pair(nextNode, newDist))
}
}
}
}
4. 결과 출력
최종적으로 도착점까지의 최단 거리를 계산하여 출력합니다.
도착점이 도달 불가능한 정점이라면, -1을 출력합니다.
dijkstra(S - 1)
val result = if (distance[E - 1] == Int.MAX_VALUE) -1 else distance[E - 1]
println(result)
코드 전체
위의 로직을 바탕으로 하나의 완전한 코드는 아래와 같습니다.
import java.util.*
fun main() {
val (N, M) = readLine()!!.split(" ").map { it.toInt() }
val graph = Array(N) { mutableListOf>() }
for (i in 0 until M) {
val (A, B, C) = readLine()!!.split(" ").map { it.toInt() }
graph[A - 1].add(Pair(B - 1, C))
}
val (S, E) = readLine()!!.split(" ").map { it.toInt() }
fun dijkstra(start: Int) {
val distance = Array(N) { Int.MAX_VALUE }
distance[start] = 0
val pq = PriorityQueue>(compareBy { it.second })
pq.add(Pair(start, 0))
while (pq.isNotEmpty()) {
val (current, dist) = pq.poll()
if (dist > distance[current]) continue
for (next in graph[current]) {
val (nextNode, weight) = next
val newDist = dist + weight
if (newDist < distance[nextNode]) {
distance[nextNode] = newDist
pq.add(Pair(nextNode, newDist))
}
}
}
return distance
}
dijkstra(S - 1)
val result = if (distance[E - 1] == Int.MAX_VALUE) -1 else distance[E - 1]
println(result)
}
결론
다익스트라 알고리즘은 다양한 문제에 적용할 수 있는 강력한 도구입니다.
코틀린으로 구현하는 과정에서 그래프의 구조를 이해하고, 알고리즘의 성능을 끌어올리기 위한 여러 가지 기법을 배울 수 있었습니다.
복잡한 문제를 단순하게 푸는 접근 방법을 익히고, 이를 코드로 구현하는 연습이 필요합니다.
또한 다익스트라 알고리즘을 활용하여 현실 세계의 다양한 최단 경로 문제를 해결하는 능력을 키워보시기 바랍니다.