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

Single Source Shortest Path II

For a given weighted graph $G = (V, E)$, find the shortest path from a source to each vertex. For each vertex $u$, print the total weight of edges on the shortest path from vertex $0$ to $u$.

Input

In the first line, an integer $n$ denoting the number of vertices in $G$ is given. In the following $n$ lines, adjacency lists for each vertex $u$ are respectively given in the following format:

$u$ $k$ $v_1$ $c_1$ $v_2$ $c_2$ ... $v_k$ $c_k$

Vertices in $G$ are named with IDs $0, 1, ..., n-1$. $u$ is ID of the target vertex and $k$ denotes its degree. $v_i (i = 1, 2, ... k)$ denote IDs of vertices adjacent to $u$ and $c_i$ denotes the weight of a directed edge connecting $u$ and $v_i$ (from $u$ to $v_i$).

Output

For each vertex, print its ID and the distance separated by a space character in a line respectively. Print in order of vertex IDs.

Constraints

$1 \leq n \leq 10,000$

$0 \leq c_i \leq 100,000$

$|E| < 500,000$

All vertices are reachable from vertex $0$

Sample Input 1

5
0 3 2 3 3 1 1 2
1 2 0 2 3 4
2 3 0 3 3 1 4 1
3 4 2 1 0 1 1 4 4 3
4 2 2 1 3 3

Sample Output 1

0 0
1 2
2 2
3 1
4 3

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.reflect.ClassTag;
import scala.io.StdIn.{readInt, readLine};

object Main {
    def main(args: Array[String]): Unit = {
        val n = readInt;
        val ig = new IntGraph(n);
        for (i <- (0 until n)) {
            val line = readLine.split(" ").map(_.toInt);
            val src = line(0);
            val dstCnt = line(1);
            (0 until dstCnt).foldLeft(line.drop(2).toList) { (dsts, i) =>
                dsts match {
                    case dst :: cost :: rest => ig.add(src, dst, cost); rest;
                    case _ => dsts;
                }
            }
        }
        val (d, p) = ig.shortestPath(0);
        for(i <- (0 until n)) {
            println("%d %d".format(i, d(i)));
        }
    }
}

class IntGraph(size: Int) {
    val matrix: Array[List[(Int, Int)]] = new Array[List[(Int, Int)]](size).map( e => Nil);
    
    def add(src: Int, dst: Int, cost: Int): Unit = matrix(src) = (dst, cost) :: matrix(src);
    
    def shortestPath(from: Int): (Array[Int], Array[Int]) = {
        val colors = new Array[Int](size); // 0: 未追加, 1: 追加済み
        val distances = new Array[Int](size).map(e => Int.MaxValue);
        val parents = new Array[Int](size);
        implicit val ord: Ordering[(Int, Int)] = Ordering.by((e: (Int, Int)) => e._2).reverse;
        val pq = new PriorityQueue[(Int, Int)]();
        var cnt = 0;
        def _shortestPath: Unit = {
            pq.dequeue match {
                case None => ();
                case Some((src, cost)) => {
                    if (cnt < size) {
                        if (colors(src) != 1) {
                            colors(src) = 1;
                            cnt += 1;
                            matrix(src).foreach { e =>
                                val dst = e._1;
                                val newCost = e._2 + cost;
                                if (newCost < distances(dst) && colors(dst) != 1) {
                                    distances(dst) = newCost;
                                    parents(dst) = src;
                                    pq.enqueue((dst, newCost));
                                }
                            }
                        }
                        _shortestPath;
                    }
                }
            }
        }
        distances(0) = 0;
        parents(0) = -1;
        pq.enqueue((0, distances(0)))
        _shortestPath;
        (distances, parents);
    }
}

class PriorityQueue[A](implicit ord: Ordering[A], m: ClassTag[A]) {
    import ord._;
    private var heap: Array[A] = m.newArray(10000);
    private var size = 0;
    
    def isEmpty: Boolean = size == 0;
    
    def isFull: Boolean = size == heap.length;
    
    def enqueue(elem: A): Unit = {
        def _enqueue(curr: Int): Unit = {
            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) extendsArray;
        heap(size) = elem;
        _enqueue(size);
        size += 1;
        
    }
    
    def dequeue(): Option[A] = {
        if (isEmpty) {
            None;
        } else if (size == 1) {
            size -= 1;
            Some(heap(0));
        } else {
            val top = heap(0);
            heap(0) = heap(size - 1);
            size -= 1;
            heapify(0);
            Some(top);
        }
    }
    
    private def heapify(from: Int): Unit = {
        val left = from * 2 + 1;
        val right = from * 2 + 2;
        if (right < size) {
            val maxIdx = max(from, left, right);
            if (maxIdx > from) {
                swap(from, maxIdx);
                heapify(maxIdx);
            }
        } else if (left < size && heap(left) > heap(from)) {
            swap(from, left);
        }
    }
    
    private def swap(a: Int, b: Int): Unit = {
        val tmp = heap(a);
        heap(a) = heap(b);
        heap(b) = tmp;
    }
    
    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 extendsArray(): Unit = {
        val tmp = m.newArray((heap.length * 1.5).toInt);
        heap.copyToArray(tmp);
        heap = tmp;
    }
}