PS(Problem Solving)/BOJ

[백준/BOJ] 1197번: 최소 스패닝 트리

JunsuKim 2022. 7. 22.
728x90

문제

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

 

1197번: 최소 스패닝 트리

첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

www.acmicpc.net

해설

최소 신장 트리의 기본적인 문제이다.

크루스칼 알고리즘과 프림 알고리즘으로 해결이 가능한데, 나는 우선 크루스칼 알 고리즘을 이용하여 해결하였다.

크루스칼 알고리즘은 가중치가 가장 작은 간선부터 선택해 나가는 알고리즘이다.

자세한 설명은 아래를 참고하면 된다.

https://jjunsu.tistory.com/221

 

[알고리즘] 크루스칼 알고리즘(Kruscal Algorithm)

크루스칼 알고리즘(Kruskal Algorithm) 크루스칼 알고리즘은 그리디 알고리즘(Greedy Algorithm)의 일종이다. 크루스칼 알고리즘은 가중치가 가장 작은 간선으로부터 시작한다. 위에서 보았던 연결 그래

jjunsu.tistory.com

소스 코드

import java.util.*

private lateinit var parent: IntArray

data class Element(val start: Int, val end: Int, val cost: Int): Comparable<Element> {
    override fun compareTo(other: Element): Int = cost - other.cost
}

fun main() = with(System.`in`.bufferedReader()) {
    val (nodeCnt, edgeCnt) = readLine().split(" ").map { it.toInt() }
    parent = IntArray(nodeCnt + 1)
    repeat(nodeCnt) { i -> parent[i] = i }

    val pq = PriorityQueue<Element>()
    repeat(edgeCnt) {
        val (start, end, cost) = readLine().split(" ").map { it.toInt() }
        pq.add(Element(start, end, cost))
    }

    var ans = 0
    repeat(edgeCnt) { i ->
        val ele = pq.poll()
        if(find(ele.start) != find(ele.end)) {
            union(ele.start, ele.end)
            ans += ele.cost
        }
    }

    println(ans)
}

private fun union(a: Int, b: Int) {
    val aParent = find(a)
    val bParent = find(b)

    if(aParent != bParent) parent[bParent] = aParent
}

private fun find(i: Int): Int {
    if(parent[i] != i) parent[i] = find(parent[i])
    return parent[i]
}
728x90

댓글