문제
1774번: 우주신과의 교감
(1,1) (3,1) (2,3) (4,3) 이렇게 우주신들과 황선자씨의 좌표가 주어졌고 1번하고 4번이 연결되어 있다. 그렇다면 1번하고 2번을 잇는 통로를 만들고 3번하고 4번을 잇는 통로를 만들면 신들과 선자씨끼
www.acmicpc.net
풀이
최소 스패닝 트리를 구하는 문제로 프림과 크루스칼 알고리즘을 이용해 풀이할 수 있다. 이번 문제에서는 크루스칼 알고리즘을 사용하였다.
문제는 각 정점의 위치가 주어지기 때문에, 정점들 간의 거리를 계산하여 간선의 정보를 리스트에 저장해준다. 그리고 나서 크루스칼 알고리즘을 이용하여 최소 스패닝 트리를 구하고 결과를 출력해준다.
코드
import java.util.*
import kotlin.math.*
// 별의 좌표를 저장하는 데이터 클래스
data class Star(val x: Int, val y: Int, val index: Int)
// 간선을 나타내는 데이터 클래스
data class Edge(val start: Int, val end: Int, val value: Double) : Comparable<Edge> {
override fun compareTo(other: Edge): Int = value.compareTo(other.value)
}
// 두 별 사이의 거리 계산 함수
fun distance(start: Star, end: Star) = sqrt((start.x - end.x).toDouble().pow(2) + (start.y - end.y).toDouble().pow(2))
fun main() {
val br = System.`in`.bufferedReader()
val bw = System.out.bufferedWriter()
// 입력
val st = StringTokenizer(br.readLine())
val num = st.nextToken().toInt() // 별의 개수
val root = st.nextToken().toInt() // 초기에 선택된 별의 개수
// 별의 좌표 정보 저장
val list = ArrayList<Star>(num)
// 간선 정보 저장을 위한 리스트
val graph = ArrayList<Edge>(num)
repeat(num) {
with(StringTokenizer(br.readLine())) {
list.add(Star(nextToken().toInt(), nextToken().toInt(), it + 1))
}
}
// 모든 별 간의 거리를 계산하여 간선 정보 저장
for (i in 0 until num) {
for (j in i + 1 until num) {
graph.add(Edge(list[i].index, list[j].index, distance(list[i], list[j])))
}
}
graph.sort() // 거리 순으로 정렬
// 유니온-파인드를 위한 부모 배열 초기화
val parent = IntArray(num + 1) { it }
// 유니온-파인드에서 루트 찾기 함수
fun find(a: Int) : Int {
return if(parent[a]==a) a
else find(parent[a])
}
// 두 집합 합치기 함수
fun union(a: Int, b: Int) {
val x = find(a)
val y = find(b)
if (x != y) {
parent[y] = x
}
}
// 크루스칼 알고리즘을 이용한 최소 스패닝 트리 계산 함수
fun kruskal(): Double {
var ans = 0.0
// 간선을 하나씩 확인하며 사이클이 생기지 않으면 해당 간선을 선택
for (edge in graph) {
if (find(edge.start) != find(edge.end)) {
ans += edge.value
union(edge.start, edge.end)
}
}
return ans
}
// 초기 선택된 별들을 하나의 집합으로 합치기
repeat(root) {
with(StringTokenizer(br.readLine())) {
union(nextToken().toInt(), nextToken().toInt())
}
}
// 결과 출력
bw.write(String.format("%.2f", kruskal()))
bw.flush()
bw.close()
br.close()
}
'알고리즘 > Baekjoon' 카테고리의 다른 글
[백준] 17472번: 다리 만들기 2 - Kotlin[코틀린] (0) | 2023.11.24 |
---|---|
[백준] 6479번: 전력난 - Kotlin[코틀린] (0) | 2023.11.22 |
[백준] 4386번: 별자리 만들기 - Kotlin[코틀린] (0) | 2023.11.14 |
[백준] 1197번: 최소 스패닝 트리 - Kotlin[코틀린] (0) | 2023.11.09 |
[백준] 9372번: 상근이의 여행 - Kotlin[코틀린] (0) | 2023.11.08 |