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 C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <stdbool.h>

typedef struct {
  unsigned int predecessor; // initial  vertex, tail
  unsigned int successor;   // terminal vertex, head
  unsigned int cost;
} Edge;
  
typedef struct {
  unsigned int id;
  unsigned int outDegree;
  Edge* edges;
  unsigned int minCost;
} Node;

typedef struct {
  Node* nodes;
  unsigned int size;
} Graph;

typedef Node HeapElementType;
typedef bool (*CompareFunc)(HeapElementType, HeapElementType);

typedef struct {
  HeapElementType* heap;
  unsigned int size;
  unsigned int maxSize;
  CompareFunc cmp;
} PriorityQueue;

void heapify(HeapElementType*, unsigned int, CompareFunc, unsigned int);
bool compare(HeapElementType, HeapElementType);

void insert(PriorityQueue*, HeapElementType);
HeapElementType extract(PriorityQueue*);

void dijkstra(Graph*, unsigned int);

int main () {
  int n;
  int id, k, v, c;  
  Graph graph;
  
  scanf("%d", &n);
  graph.size  = n;
  graph.nodes = (Node*)malloc(sizeof(Node)*n);
  for (unsigned int i = 0; i < n; ++i) {
    scanf("%d %d", &id, &k);
    graph.nodes[id].id        = id;
    graph.nodes[id].outDegree = k;
    graph.nodes[id].edges     = (Edge*)malloc(sizeof(Edge)*k);
    for (unsigned int j = 0; j < k; ++j) {
      scanf("%d %d", &v, &c);
      graph.nodes[id].edges[j].predecessor = id;
      graph.nodes[id].edges[j].successor   = v;
      graph.nodes[id].edges[j].cost        = c;
    }
  }

  dijkstra(&graph, 0);

  for (unsigned int i = 0; i < n; ++i) {
    printf("%u %u\n", i, graph.nodes[i].minCost);
  }
  
  return 0;
}

bool compare (HeapElementType x, HeapElementType y) {
  return x.minCost < y.minCost;
}

void heapify (HeapElementType* heap, unsigned int H, CompareFunc cmp, unsigned int i) {
  unsigned int left  = 2*i;
  unsigned int right = 2*i + 1;

  unsigned int target;
  if (left <= H && cmp(heap[left], heap[i])) {
    target = left;
  } else {
    target = i;
  }

  if (right <= H && cmp(heap[right], heap[target])) {
    target = right;
  }

  if (target != i) {
    HeapElementType t = heap[i];
    heap[i] = heap[target];
    heap[target] = t;
    heapify(heap, H, cmp, target);
  }
}

void insert (PriorityQueue* pQueue, HeapElementType key) {
  pQueue->size++;
  if (pQueue->size > pQueue->maxSize) {
    pQueue->maxSize <<= 2;
    pQueue->heap = (HeapElementType*)realloc(pQueue->heap, sizeof(HeapElementType)*(pQueue->maxSize + 1));
  }

  pQueue->heap[pQueue->size] = key;

  unsigned int target = pQueue->size;
  while (target >= 2) {
    unsigned int parent = target/2;
    if (pQueue->cmp(pQueue->heap[parent], pQueue->heap[target])) {
      break;
    } else {
      HeapElementType t = pQueue->heap[parent];
      pQueue->heap[parent] = pQueue->heap[target];
      pQueue->heap[target] = t;
      target = parent;
    }
  }
}

HeapElementType extract (PriorityQueue* pQueue) {
  HeapElementType key = pQueue->heap[1];
  pQueue->heap[1] = pQueue->heap[pQueue->size];
  pQueue->size--;  
  heapify(pQueue->heap, pQueue->size, pQueue->cmp, 1);

  return key;
}

void dijkstra (Graph* graph, unsigned int s) {
  PriorityQueue pQueue;

  pQueue.maxSize = 1;
  pQueue.heap = (HeapElementType*)malloc(sizeof(HeapElementType)*(pQueue.maxSize + 1));
  pQueue.size = 0;
  pQueue.cmp  = compare;

  bool* isVisited = (bool*)malloc(sizeof(bool)*graph->size);
  for (unsigned int i = 0; i < graph->size; ++i) {
    graph->nodes[i].minCost   = i == s ? 0 : UINT_MAX;
    isVisited[i] = false;
    insert(&pQueue, graph->nodes[i]);
  }

  while (pQueue.size != 0) {
    Node current = extract(&pQueue);
    if (!isVisited[current.id]) {
      isVisited[current.id] = true;
      for (unsigned int i = 0; i < current.outDegree; ++i) {
	unsigned int minCost = current.minCost + current.edges[i].cost;
	
	if (graph->nodes[current.edges[i].successor].minCost > minCost) {
	  graph->nodes[current.edges[i].successor].minCost = minCost;
	  insert(&pQueue, graph->nodes[current.edges[i].successor]);
	}
      }
    }
  }
}