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>
#define WHITE 0
#define GRAY 1
#define BLACK 2
#define INFTY 500000
#define MAX 10000

typedef struct{
  int color; //全て白(0)に初期化済み
  int distance;
  int parent;
}DOT;

typedef struct{
  int to;
  int dis;
}Gyou;

DOT A[MAX];
DOT pq[20000];//これで限界
Gyou *G[MAX];

//===================
int H;//PQのtail　==0でempty

void swap_pq(DOT *a,DOT *b){
  DOT c=*a;*a=*b;*b=c;
}

void maxHeapify(int i){
  int l = 2*i;
  int r = 2*i+1;
  int largest;
  // 左の子、自分、右の子で値が最大のノードを選ぶ
  if(l <= H && pq[l].distance > pq[i].distance)largest = l;
  else largest = i;
  if(r <= H && pq[r].distance > pq[largest].distance)largest = r;
  // i の子の方が値が大きい場合
  if(largest != i){
    swap_pq(&pq[i],&pq[largest]); 
    maxHeapify(largest); // 再帰的に呼び出し
  }
}

void Insert(DOT X){
  int i;
  i=++H;

  pq[i]=X;  
  while(i>=2&&pq[i/2].distance<pq[i].distance){
    swap_pq(&pq[i],&pq[i/2]);
    i=i/2;
  }
}

DOT Extract(void){
  DOT max;
  
  max=pq[1];
  pq[1]=pq[H--];
  maxHeapify(1);
  return max;
}
//=====================
int MinTree(int n){
  int total=0;
  
  
  int i;
  int u,v;
  DOT waste;

  int min_box=INFTY;
  int flag=0;
 
  int gyou_size;
    
  A[0].distance=0;
  waste.distance=0;
  waste.parent=0;
  Insert(waste);
  
  while(H!=0){
    waste=Extract();
    u=waste.parent;
    //左はmaxや最少でない可能性あり、右はextractから出てきたため,そこまでの最少
    // if(A[u].distance<waste.distance*(-1))continue;
    A[u].color=BLACK;

    gyou_size=0;//列のサイズ調べる
    for(i=0;i<n;i++){
      if(G[u][i].dis==-1)break;
      gyou_size++;
    }
           
    for(i=0;i<gyou_size;i++){//uから伸びてる手で一番短いもの探索
      v=G[u][i].to;
      if(A[v].color!=BLACK && A[v].distance > A[u].distance + G[u][i].dis){
	A[v].distance=A[u].distance+G[u][i].dis;//~v=~u+u~vで最少~ｖの
	
	waste.distance=A[v].distance*(-1);
	waste.parent=v;
	Insert(waste);

	A[v].color=GRAY;
      }
    }
  }
  //for(v=1;v<n;v++){
  // total+=G[v][A[v].parent].dis;
  //}
  return total;
}
//======================================
int main(){
  int n;
  int i,j,k;
  int dis,agree,from,to;
  
  for(i=0;i<MAX;i++){//INITIATE 
    A[i].parent=-1;
    A[i].distance=INFTY;
  }
 
  scanf("%d",&n);//INPUT
    
  for(i=0;i<n;i++){//線形グラフ作る列がそれぞれ違う
    scanf("%d%d",&from,&agree);

    G[i]=malloc(sizeof(Gyou)*(agree+1));//最後に余分に-1のgyou作成
    G[i][agree].dis=-1;
    
    for(j=0;j<agree;j++){
      scanf("%d%d",&to,&dis);
      G[from][j].to=to;
      G[from][j].dis=dis;
    }
  }

  MinTree(n);
  
  for(i=0;i<n;i++){
    printf("%d %d\n",i,A[i].distance);//PRINT
  }
  return 0;
}