728x90
문제
https://www.acmicpc.net/problem/14621
해설
연결그래프에서 최소 신장 트리를 찾는 문제이다.
고려할 점은 다음과 같다.
- 연결된 두 노드가 남초, 여초 학교여야 한다.
두 노드가 모두 남초거나, 여초라면 연결되지 않는다.
만약 두 노드가 같다면, 우선순위 큐에 넣을 필요가 없다. - 두 노드간 한 개의 간선만 있는 것이 아니라 여러 개의 간선이 있을 수 있고, 이들 간 거리는 다를 수 있다.
이는 우선순위큐를 사용할 것이기에 신경쓰지 않아도 된다.
짧은 비용부터 계산을 해주면 되기 때문이다 - 모든 노드(학교)가 연결되지 않는다면 -1을 출력한다.
연결된 노드의 개수를 저장할 변수를 선언해준다.
마지막에 노드의 개수가 (학교의 개수 - 1)개라면 모든 노드가 연결된 것이다.
위의 3가지를 제외하면 크루스칼 알고리즘의 기본을 따라가면 된다.
크루스칼 알고리즘에 대해 잘 모른다면 크루스칼 알고리즘을 참고하면 좋을 것이다.
소스 코드
import java.util.*
private lateinit var parent: IntArray
data class Connect(val start: Int, val end: Int, val cost: Int): Comparable<Connect> {
override fun compareTo(other: Connect): Int = cost - other.cost
}
fun main() = with(System.`in`.bufferedReader()) {
val (nodeCnt, edgeCnt) = readLine().split(" ").map { it.toInt() }
parent = IntArray(nodeCnt + 1)
repeat(nodeCnt + 1) { i -> parent[i] = i }
val boyOrGirl = readLine().split(" ")
val section = Array(nodeCnt + 1 ) { "" }
for(i in 1..nodeCnt) section[i] = boyOrGirl[i-1]
val pq = PriorityQueue<Connect>()
repeat(edgeCnt) {
val (start, end, cost) = readLine().split(" ").map { it.toInt() }
if(section[start] != section[end]) pq.add(Connect(start, end, cost))
}
var ans = 0
var cnt = 0
while(pq.isNotEmpty()) {
val cur = pq.poll()
if(find(cur.start) != find(cur.end)) {
union(cur.start, cur.end)
ans += cur.cost
cnt++
}
}
if(cnt != nodeCnt - 1) println(-1)
else println(ans)
}
private fun union(a: Int, b: Int) {
val aParent = find(a)
val bParent = find(b)
parent[bParent] = aParent
}
private fun find(i: Int): Int {
if(parent[i] != i) parent[i] = find(parent[i])
return parent[i]
}
728x90
'PS(Problem Solving) > BOJ' 카테고리의 다른 글
[백준/BOJ] 1647번: 도시 분할 계획 (1) | 2022.07.27 |
---|---|
[백준/BOJ] 13418번: 학교 탐방하기 (0) | 2022.07.26 |
[백준/BOJ] 16398번: 행성 연결 (0) | 2022.07.24 |
[백준/BOJ] 11725번: 트리의 부모 찾기 (0) | 2022.07.23 |
[백준/BOJ] 1197번: 최소 스패닝 트리 (0) | 2022.07.22 |
댓글