Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Minimum Spanning Tree

For a given weighted graph $G = (V, E)$, find the minimum spanning tree (MST) of $G$ and print total weight of edges belong to the MST.

Input

In the first line, an integer $n$ denoting the number of vertices in $G$ is given. In the following $n$ lines, a $n \times n$ adjacency matrix $A$ which represents $G$ is given.
$a_{ij}$ denotes the weight of edge connecting vertex $i$ and vertex $j$. If there is no edge between $i$ and $j$, $a_{ij}$ is given by -1.

Output

Print the total weight of the minimum spanning tree of $G$.

Constraints

$1 \leq n \leq 100$

$0 \leq a_{ij} \leq 2,000$ (if $a_{ij} \neq -1$)

$a_{ij} = a_{ji}$

$G$ is a connected graph

Sample Input 1

5
-1 2 3 1 -1
2 -1 -1 4 -1
3 -1 -1 1 1
1 4 1 -1 3
-1 -1 1 3 -1

Sample Output 1

5

Reference

Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable.ArraySeq;
import scala.reflect.ClassTag;
import scala.io.StdIn.{readInt, readLine};

object Main {
    def main(args: Array[String]): Unit = {
        val n = readInt;
        val ig = new IntGraph(n);
        (0 until n).foreach { i => 
            readLine.trim.split(" ").map(_.toInt).zipWithIndex.filter( e => e._1 != -1).foreach { e => ig.add(i, e._2, e._1)}
        }
        val ret = ig.mst;
        println(ret._1.sum);
    }
}
class IntGraph(n: Int) {
    case class Node(value: Int, cost: Int);
    val matrix: Array[List[Node]] = new Array[List[Node]](n).map( e => Nil);
    
    override def toString(): String = {
        matrix.zipWithIndex.foldLeft[List[String]](Nil) { (list, e) =>
            val nodes = e._1.map( n => n.value.toString + "(" + n.cost.toString + ")"); 
            e._2.toString + " -> " + nodes.mkString(", ") :: list;
        }.reverse.mkString("\n");
    }
    
    def add(src: Int, dst: Int, cost: Int): Unit = matrix(src) = Node(dst, cost) :: matrix(src);
    
    def mst(): (Array[Int], Array[Int]) = {
        val colors = new Array[Int](n); // 0 : 未探索, 1 : 追加候補, 2 : 追加済み
        val parents = new Array[Int](n);
        val distances = new Array[Int](n).map( e => Int.MaxValue);
        val pq = new PriorityQueue[Node](n * n)(Ordering.by((e: Node) => e.cost).reverse);
        var cnt = 0;
        def _mst(): Unit = {
            pq.dequeue match {
                case None => ();
                case Some(Node(minValue, minCost)) if (colors(minValue) == 2)  => _mst;
                case Some(Node(minValue, minCost)) => {
                    colors(minValue) = 2;
                    cnt += 1;
                    if (cnt < n) {
                        matrix(minValue).foreach { e =>
                            if (e.cost < distances(e.value) && colors(e.value) != 2) {
                                colors(e.value) = 1;
                                parents(e.value) = minValue;
                                distances(e.value) = e.cost;
                                pq.enqueue(e);
                            }
                        }
                        _mst;
                    }
                }
            }
        }
        parents(0) = -1;
        distances(0) = 0;
        pq.enqueue(Node(0, distances(0)));
        _mst;
        (distances, parents);
    }
}

class PriorityQueue[A](len: Int)(implicit ord: Ordering[A]) {
    import ord._;
    private val heap = new ArraySeq[A](len);
    var size = 0;
    
    def isEmpty: Boolean = size == 0;
    
    def isFull: Boolean = size == len;
    
    def enqueue(e: A): Unit = {
        def _enqueue(curr: Int): Unit = {
            // if (curr % 2 == 0) right else left
            val parent = if (curr % 2 == 0) (curr - 2) / 2 else (curr - 1) / 2; 
            if (parent >= 0 && heap(curr) > heap(parent)) {
                swap(curr, parent);
                _enqueue(parent);
            }
        }
        if (!isFull) {
            heap(size) = e;
            _enqueue(size);
            size += 1;
        }
    }
    
    def dequeue(): Option[A] = {
        if (isEmpty) {
            None;
        } else {
            val top = heap(0);
            size -= 1;
            heap(0) = heap(size);
            heapify(0);
            Some(top);
        }
    }
    
    private def heapify(curr: Int): Unit = {
        if (curr < size) {
            val left = curr * 2 + 1;
            val right = curr * 2 + 2;
            if (right < size) {
                val maxIdx = max(curr, left, right);
                if (curr < maxIdx) {
                    swap(curr, maxIdx);
                    heapify(maxIdx);
                }
            } else if (left < size && heap(left) > heap(curr)) {
                swap(curr, left);
            }
        }
    }

    private def max(curr: Int, left: Int, right: Int): Int = {
        if (heap(curr) > heap(left)) {
            if (heap(right) > heap(curr)) right else curr;
        } else {
            if (heap(right) > heap(left)) right else left;
        }
    }

    private def swap(a: Int, b: Int): Unit = {
        val tmp = heap(a);
        heap(a) = heap(b);
        heap(b) = tmp;
    }
}