Go: package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"strconv"
)

//make priority queue
type Item struct {
	id       int
	priority int // this state is priority and distans from start
	index    int
}

type PriorityQueue []*Item

func (pq PriorityQueue) Len() int { return len(pq) }

// we want the ascending-priority-queue.
// So we use less than here.
func (pq PriorityQueue) Less(i, j int) bool {
	return pq[i].priority < pq[j].priority
}

func (pq PriorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
	pq[i].index = j
	pq[j].index = i
}

func (pq *PriorityQueue) Push(x interface{}) {
	n := len(*pq)
	item := x.(*Item)
	item.index = n
	*pq = append(*pq, item)
}

func (pq *PriorityQueue) Pop() interface{} {
	old := *pq
	n := len(old)
	item := old[n-1]
	item.index = -1 //for safety
	*pq = old[0 : n-1]
	return item
}

func (pq *PriorityQueue) update(dist int, id int) {
	for _, i := range *pq {
		if i.id == id {
			if i.priority > dist {
				i.priority = dist
			}
		}
	}
}

// the main code
func nextInt(sc *bufio.Scanner) int {
	sc.Scan()
	n, _ := strconv.Atoi(sc.Text())
	return n
}

func dikstra(dist [][]int, n int) []int {
	// preparate priority queue
	inf := 1 << 30
	pq := make(PriorityQueue, n)
	shortests := make([]int, n)
	for i := 0; i < n; i++ {
		pq[i] = &Item{
			id:       i,
			priority: inf,
			index:    i,
		}

		shortests[i] = inf
	}
	pq[0].priority = 0
	shortests[0] = 0

	for pq.Len() > 0 {
		item := heap.Pop(&pq).(*Item)
		shortests[item.id] = item.priority
		for id, d := range dist[item.id] {
			if d != -1 {
				pq.update(item.priority+d, id)
			}
		}
		heap.Init(&pq)
	}
	return shortests
}

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	// init
	n := nextInt(sc)
	dist := make([][]int, n)
	for i := 0; i < n; i++ {
		dist[i] = make([]int, n)
		for j := 0; j < n; j++ {
			dist[i][j] = -1
		}
	}

	// std Input
	for i := 0; i < n; i++ {
		u := nextInt(sc)
		k := nextInt(sc)
		for j := 0; j < k; j++ {
			v, c := nextInt(sc), nextInt(sc)
			dist[u][v] = c
		}
	}

	shortests := dikstra(dist, n)
	for i, d := range shortests {
		fmt.Printf("%d %d\n", i, d)
	}
}

C++: 
#include <iostream>
#include <cstdio>
#include <climits>
#include <cstring>

using namespace std;

#define SWAP(type, a, b) do { type t = a; a = b; b = t; } while(0)

typedef struct {
    int* verIdx;
    int num;
} Heap;

typedef struct _node {
    int toIdx;
    int weight;
    struct _node* next;
} Node;

typedef struct {
    Node* head;
} List;

int* d; 
List* list;
int n;

void makeMinHeap(Heap *heap, int idx);
void insert(Heap *heap, int key);
int extract(Heap *heap);

static inline int getParent(int idx) { return idx / 2; }
static inline int getLeft(int idx) { return idx * 2; }
static inline int getRight(int idx) { return idx * 2 + 1; }
static inline bool isCorrectHeapIdx(int idx, int heapSize) { return idx <= heapSize && 1 <= idx; }
static inline bool isEmpty(Heap *heap) { return heap->num <= 0; }

static inline int getMinCost(int idx) {
    return d[idx];
}

void makeMinHeap(Heap *heap, int idx) {
    int left = getLeft(idx);
    int right = getRight(idx);

    int minIdx = idx;
    if(isCorrectHeapIdx(left, heap->num) && getMinCost(heap->verIdx[minIdx]) > getMinCost(heap->verIdx[left])) {
        minIdx = left;
    } if(isCorrectHeapIdx(right, heap->num) && getMinCost(heap->verIdx[minIdx]) > getMinCost(heap->verIdx[right])) {
        minIdx = right;
    }

    if(minIdx != idx) {
        SWAP(int, heap->verIdx[minIdx], heap->verIdx[idx]);
        makeMinHeap(heap, minIdx);
    }
}

void insert(Heap *heap, int* key) {
    heap->verIdx[++heap->num] = *key;
    for(int i = getParent(heap->num); i >= 1; i = getParent(i)) {
        makeMinHeap(heap, i);
    }
}

void extract(Heap *heap, int* key) {
    *key = heap->verIdx[1];
    heap->verIdx[1] = heap->verIdx[heap->num--];
    makeMinHeap(heap, 1);
}

static inline void set(Node* ptr, int toIdx, int weight, Node* next) {
    ptr->toIdx = toIdx;
    ptr->weight = weight;
    ptr->next = next;
}

void addList(int s, int t, int weight) {
    Node* next = list[s].head;
    Node* newNode = new Node();

    list[s].head = newNode;
    set(newNode, t, weight, next);
}

void solve(int s) {
    Heap que;
    bool* isAddS = new bool[n]();

    que.verIdx = new int[n * n];
    que.num = 0;

    d = new int[n];
    d[s] = 0;
    for(int i = 0; i < n; i++) {
        if(s != i) {
            d[i] = INT_MAX;
        }
    }
    
    insert(&que, &s);

    while(1) {
        int u;
        while(1) {
            if(isEmpty(&que)) {
                return;
            } 

            extract(&que, &u);
            if(!isAddS[u]) {
                break;
            }
        }

        isAddS[u] = true;

        Node* ptr = list[u].head;
        while(ptr != NULL) {
            int v = ptr->toIdx;
            if(!isAddS[v]) {
                int weight = ptr->weight;
                if(d[u] + weight < d[v]) {
                    d[v] = d[u] + weight;
                }
                insert(&que, &v);
            }
            ptr = ptr->next;
        }
    }

    return;
}

int main() {

    scanf("%d", &n);

    list = new List[n];
    for(int i = 0; i < n; i++) {
        list[i].head = NULL;
    }
    

    for(int i = 0; i < n; i++) {
        int s;
        int deg;

        scanf("%d %d", &s, &deg);
        for(int j = 0; j < deg; j++) {
            int t;
            int w;

            scanf("%d %d", &t, &w);

            addList(s, t, w);
        }
    }

    solve(0);

    for(int i = 0; i < n; i++) {
        cout << i << " " << d[i] << endl;
    }
}

C++: //
// Created by 李青坪 on 2018/11/8.
//
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#define INFINITY 1<<21
#define NIL -1
#define MAXN 10000

using namespace std;
struct Node{
    int id;
    int weight;
    friend bool operator < (Node x1, Node x2) {
        return x1.weight < x2.weight;
    }
};

struct cmp{
    bool operator ()(Node &a, Node &b){
        return a.weight > b.weight;
    }
};

vector<Node> graph[MAXN];
priority_queue<Node, vector<Node>, cmp> V_S;
int n;
int d[MAXN];
bool visited[MAXN];

void init(){
    fill(d, d+MAXN, INFINITY);
    d[0] = 0;
    fill(visited, visited+MAXN, false);
    Node node;
    node.id = 0;
    node.weight = 0;
    V_S.push(node);
}

void updateMinWeight(Node u){
    vector<Node>::iterator it;
    for (it = graph[u.id].begin(); it != graph[u.id].end(); ++it){ //遍历与u相连的所有结点，看有没有结点到S的距离减小了
        if (visited[(*it).id]) continue;
        if (d[(*it).id] > d[u.id] + (*it).weight){
            d[(*it).id] = d[u.id] + (*it).weight;
            Node node;
            node.id = (*it).id;
            node.weight = d[(*it).id];
            V_S.push(node);
        }
    }
}

void dijkstra(){
    while (!V_S.empty()){
        Node u = V_S.top();
        V_S.pop();
        visited[u.id] = true;
        updateMinWeight(u);
    }
}

int main(){
    scanf("%d", &n);
    int u, k;
    for (int i = 0; i < n; ++i) {
        scanf("%d %d", &u, &k);
        int v, w;
        Node node;
        for (int j = 0; j < k; ++j) {
            scanf("%d %d", &v, &w);
            node.id = v;
            node.weight = w;
            graph[u].push_back(node);
        }
    }
    init();
    dijkstra();
    for (int l = 0; l < n; ++l) {
        printf("%d %d\n", l, d[l]);
    }
//    Node l[6];
//    l[0].id = 0; l[0].weight = 3;
//    l[1].id = 1; l[1].weight = 2;
//    l[2].id = 2; l[2].weight = 5;
//    l[3].id = 3; l[3].weight = 3;
//    l[4].id = 4; l[4].weight = 4;
//    l[5].id = 5; l[5].weight = 2;
//    for (int i = 0; i < 6; ++i) {
//        V_S.push(l[i]);
//    }
//    for (int j = 0; j < 6; ++j) {
//        printf("id: %d weight: %d\n", V_S.top().id, V_S.top().weight);
//        V_S.pop();
//    }
}
/*
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
 */