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
	heap.Init(&pq)

	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 <cstdlib>
#include <stack>
#include <vector>
#include <algorithm>
#include <cmath>
#include <climits>
#include <cstring>
#include <queue>
#include <string>

using namespace std;

const double PI = 3.14159265358979;

//int G[101][101];
int visited[10001];
int n;

int d[10001];


struct Vertex {
	int u;
	int weight;

	friend bool operator < (Vertex a, Vertex b) {
		return a.weight > b.weight;
	}
};

vector<Vertex> G[10001];

void dijkstra(int start) {

	priority_queue<Vertex> PQ;

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

	d[start] = 0;
	PQ.push(Vertex{ 0,0 });

	while (!PQ.empty()) {
		Vertex f = PQ.top();
		PQ.pop();
		int u = f.u;
		if (visited[u]) {
			continue;
		}
		else {
			visited[u] = 1;
		}

		//if (f.weight > d[u]) continue;

		
		for (int j = 0; j < G[u].size(); j++)
		{
			int v = G[u][j].u;
			if (!visited[v]) {
				if (d[u] + G[u][j].weight < d[v]) {
					PQ.push(Vertex{ v, d[u] + G[u][j].weight });
					d[v] = d[u] + G[u][j].weight;
				}
			}
		}
	}


}

int main() {
	
	
	cin >> n;

	for (int i = 0; i < n; i++)	{
		int u, k; cin >> u >> k;
		for (int j = 0; j < k; j++)	{
			int v, w; cin >> v >> w;
			G[u].push_back(Vertex{ v, w });
		}
	}

	dijkstra(0);

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

	return 0;
}

C++: #include <iostream>
#include <queue>
#include <utility>
#include <vector>

#define MAX_NODE 10000
#define INF 1000000000

using namespace std;

struct Edge {
	int to, w;
};

typedef pair<int, int> P;

vector<Edge> adj[MAX_NODE];
int d[MAX_NODE];

void dijkstra(int n, int start) {
	priority_queue<P, vector<P>, greater<P> > heap;
	fill(d, d + n, INF);
	d[start] = 0;
	heap.push({0, start});

	while (!heap.empty()) {
 		P p = heap.top();
 		heap.pop();
 		int from = p.second;
 		if (d[from] < p.first)
 			continue;
 		for (int i = 0; i < adj[from].size(); i++) {
 			Edge e = adj[from][i];
	 		if (d[from] + e.w < d[e.to]) {
	 			d[e.to] = d[from] + e.w;
	 			heap.push( {d[e.to], e.to} );
	 		}
	 	}
	}
}

int main(){
	int n,u,k,c,v;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>u>>k;
		for(int j=0;j<k;j++){
			cin>>v>>c;
			adj[u].push_back({v,c});
		}
	}
	dijkstra(n,0);
	for(int i=0;i<n;i++){
		cout<<i<<" "<<d[i]<<"\n";
	}
	return 0;
}

C++: #include <iostream>
#include <vector>
using namespace std;
int n;
/*
int dat[100][100];
int cost[100];
int done[100];

void prim(){
	for(int i=0;i<n;i++){
		cost[i]=1<<21;
		done[i]=0;
	}
	int s=0;	
	int next, ncost=1<<21;
	done[s]=1;
	cost[s]=0;
	while(1){
		ncost=1<<21;
		for(int j=0;j<n;j++){
			if(done[j]){
				for(int i=0;i<n;i++){
					if(dat[j][i]!=-1){
						if(cost[i]>=dat[j][i]&&!done[i]){
							cost[i]=dat[j][i];
						}
						if(ncost>cost[i]&&!done[i]){
							next=i;
							ncost=cost[i];
						}
					}
				}
			}
		}
//		cout<<"next:"<<next<<" cost:"<<cost[next]<<endl;
		done[next]=1;
		int flag=true;
		for(int i=0;i<n;i++){
			if(!done[i]) flag = false;
		}
		if(flag)
			return;
	}
}


void dijk(){
	for(int i=0;i<n;i++){
		cost[i]=1<<21;
		done[i]=0;
	}
	int s=0;	
	int next, ncost=1<<21;
	done[s]=1;
	cost[s]=0;
	while(1){
		ncost=1<<21;
		for(int j=0;j<n;j++){
			if(done[j]){
				for(int i=0;i<n;i++){
					if(dat[j][i]!=0){
						if(cost[i]>=dat[j][i]+cost[j]){
							cost[i]=dat[j][i]+cost[j];
						}
						if(ncost>cost[i]&&!done[i]){
							next=i;
							ncost=cost[i];
						}
					}
				}
			}
		}
//		cout<<"next:"<<next<<" cost:"<<cost[next]<<endl;
		done[next]=1;
		int flag=true;
		for(int i=0;i<n;i++){
			if(!done[i]) flag = false;
		}
		if(flag)
			return;
	}
}
*/

vector<vector<int> > dat;
int cost[10000];
int done[10000];

void dijk2(){
	for(int i=0;i<n;i++){
		cost[i]=1<<21;
		done[i]=0;
	}
	int s=0;	
	int next, ncost=1<<21;
	done[s]=1;
	cost[s]=0;
	while(1){
		top:
		ncost=1<<21;
		for(int j=0;j<n;j++){
			if(done[j]){
				for(int i=0;i<n;i++){
					if(dat[j][i]!=0){
						if(!done[i]){
							if(cost[i]>=dat[j][i]+cost[j]){
								cost[i]=dat[j][i]+cost[j];
							}
							if(ncost>cost[i]){
								next=i;
								ncost=cost[i];
							}
						}
					}
				}
			}
		}
//		cout<<"next:"<<next<<" cost:"<<cost[next]<<endl;
		done[next]=1;
		for(int i=0;i<n;i++){
			if(!done[i]) goto top;
		}
		return;
	}
}



int main(){
	int num, from, dist, c;
	cin>>n;	
	dat.reserve(n);
	for(int i=0;i<n;i++){
		vector<int> d(n);
		dat.push_back(d);
	}
	for(int i=0;i<n;i++){
		cin>>from>>num;
		for(int j=0;j<num;j++){
			cin>>dist>>c;
			dat[from][dist]=c;
		}
	}
	dijk2();
	for(int i=0;i<n;i++){
		cout<<i<<" "<<cost[i]<<endl;
	}
	return 0;
}

C++: #include <bits/stdc++.h>

using namespace std;

vector<int> adja[10000], cost[10000];

#define INF (1 << 30)

int main() {
	int n, id, k;

	cin >> n;
	for (int i = 0; i < n; ++i) {
		cin >> id >> k;
		adja[id].resize(k);
		cost[id].resize(k);
		for (int j = 0; j < k; ++j) {
			cin >> adja[id][j] >> cost[id][j];
		}
	}

	priority_queue<pair<int, int>> que;
	que.push(make_pair(0, 0)); //cost, node
	int best[10000];
	fill(best, best + n, INF);
	best[0] = 0;

	while (!que.empty()) {
		pair<int, int> top = que.top();
		que.pop();

		if (best[top.second] < top.first) {
			continue;
		}

		for (int j = 0, len = adja[top.second].size(); j < len; ++j) {
			if (best[adja[top.second][j]] > top.first + cost[top.second][j]) {
				best[adja[top.second][j]] = top.first + cost[top.second][j];
				que.push(make_pair(top.first + cost[top.second][j], adja[top.second][j]));
			}
		}
	}

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

	return 0;
}