MST:KruskalアルゴリズムとPrimアルゴリズム
チップ.
1.まずUnion Findの3つの関数を作成します.(findUnion, isUnion, union)
2.Kruskalアルゴリズムは、コストが小さいから合併がないまで追加する方法である.
したがって,ソート後は最小のものから開始すればよいが,これを便利にPriorityQueueとして含み,その後コストを基準に最小の値から抽出を開始すれば終了する.
しかし,MSTを解く際には,Kruskalを盲目的に信じることはできない.
BOJ 2887(惑星トンネル)の問題では、最大100000個の頂点がある.
なぜなら、他の問題には2つの状況があるからだ.
1.定点の数が少ないため、必然的に幹線の本数も少ない
2.頂点数が多くても、一部の頂点がつながっているなど、幹線数が少ない
このような場合は、幹線の本数が小さくて通りやすいです.
しかし、これは問題ではありません.頂点が10万個なので、幹線はたっぷり(10万-1)!犬.
数十億で十分だと思います.インターネット上の工場計算機も5000しかありません.
KruskalではなくPrimアルゴリズム.でもPrimでこれを
nは10万なのでn^2=100億です.
その実用的なKruskalも解くことができますxyzを誠実に保存するのではなく、他の方法で保存します.
https://chanhuiseok.github.io/posts/baek-34/
クルーズとフリームの違いは
https://gmlwjd9405.github.io/2018/08/29/algorithm-kruskal-mst.html
こちらはよく整理されています
PREAMアルゴリズムの起動方式はDAEXTRAと似ているそうです.
https://www.apexcel.blog/algorithm/graph/mst/mst/
クルーズとは異なり、フリームは各頂点の情報を必要とするため、各頂点には隣接する頂点の情報が必要である.したがって、2 D配列には、各頂点の隣接する頂点の情報が含まれます.
整理すると、グラフィック内にわずかな数字しかない「 図表に多数の幹線が存在する「 PrimアルゴリズムはUnion Findを使う必要がないので便利です.
1.まずUnion Findの3つの関数を作成します.(findUnion, isUnion, union)
2.Kruskalアルゴリズムは、コストが小さいから合併がないまで追加する方法である.
したがって,ソート後は最小のものから開始すればよいが,これを便利にPriorityQueueとして含み,その後コストを基準に最小の値から抽出を開始すれば終了する.
しかし,MSTを解く際には,Kruskalを盲目的に信じることはできない.
BOJ 2887(惑星トンネル)の問題では、最大100000個の頂点がある.
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.util.*
import kotlin.math.abs
class BOJ_행성터널 {
lateinit var planet: Array<List<Long>>
lateinit var root: IntArray
fun main() {
val br = BufferedReader(InputStreamReader(System.`in`))
val bw = BufferedWriter(OutputStreamWriter(System.`out`))
val n = br.readLine().toInt()
planet = Array(n) { emptyList<Long>() }
root = IntArray(n) { it }
for (i in 0 until n) {
planet[i] = br.readLine().split(" ").map { it.toLong() }
}
val pq = PriorityQueue<List<Long>>(compareBy { it.last() })
for (i in planet.indices) {
for (j in i + 1 until planet.size) {
pq.offer(listOf(i.toLong(), j.toLong(), getDistance(i, j)))
}
}
var answer = 0L
while (pq.isNotEmpty()) {
val (aLong, bLong, dist) = pq.poll()
val a = aLong.toInt()
val b = bLong.toInt()
if (isUnion(a, b)) continue
union(a, b)
answer += dist
}
bw.write("$answer")
br.close()
bw.close()
}
fun getDistance(planetA: Int, planetB: Int): Long {
val a = planet[planetA]
val b = planet[planetB]
return minOf(abs(a[0] - b[0]), abs(a[1] - b[1]), abs(a[2] - b[2]))
}
fun union(a: Int, b: Int) {
val (min, max) = listOf(findUnion(a), findUnion(b)).sorted()
root[max] = min
}
fun isUnion(a: Int, b: Int): Boolean {
return findUnion(a) == findUnion(b)
}
fun findUnion(a: Int): Int {
if (a == root[a]) return a
root[a] = findUnion(root[a])
return root[a]
}
}
このように解くと他の問題のように簡単に通過すると思いますが、メモリが超過しています.なぜなら、他の問題には2つの状況があるからだ.
1.定点の数が少ないため、必然的に幹線の本数も少ない
2.頂点数が多くても、一部の頂点がつながっているなど、幹線数が少ない
このような場合は、幹線の本数が小さくて通りやすいです.
しかし、これは問題ではありません.頂点が10万個なので、幹線はたっぷり(10万-1)!犬.
数十億で十分だと思います.インターネット上の工場計算機も5000しかありません.
KruskalではなくPrimアルゴリズム.でもPrimでこれを
nは10万なのでn^2=100億です.
その実用的なKruskalも解くことができますxyzを誠実に保存するのではなく、他の方法で保存します.
https://chanhuiseok.github.io/posts/baek-34/
クルーズとフリームの違いは
https://gmlwjd9405.github.io/2018/08/29/algorithm-kruskal-mst.html
こちらはよく整理されています
PREAMアルゴリズムの起動方式はDAEXTRAと似ているそうです.
https://www.apexcel.blog/algorithm/graph/mst/mst/
クルーズとは異なり、フリームは各頂点の情報を必要とするため、各頂点には隣接する頂点の情報が必要である.したがって、2 D配列には、各頂点の隣接する頂点の情報が含まれます.
整理すると、
Kruskal 알고리즘
時間複雑度はO(elog₂e)
Prim의 알고리즘
時間複雑度はO(n^2)
희소 그래프(Sparse Graph)
」にはKruskalアルゴリズムが適している;밀집 그래프(Dense Graph)
」には、Primアルゴリズムが適切である.Reference
この問題について(MST:KruskalアルゴリズムとPrimアルゴリズム), 我々は、より多くの情報をここで見つけました https://velog.io/@s10th24b/MST-Kruskal-Algorithmテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol