Go: package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

const (
	INFTY = 1 << 21
	NIL   = -1
)

const (
	WHITE = iota
	GRAY
	BLACK
)

type Graph [][]int

func (g *Graph) dikstra(n int) string {
	var (
		u, minv = 0, 0
	)

	d := make([]int, n)
	color := make([]int, n)

	for i := 0; i < n; i++ {
		d[i] = INFTY
		color[i] = WHITE
	}
	d[0] = 0
	color[0] = GRAY

	for {
		minv = INFTY
		u = -1
		for i := 0; i < n; i++ {
			if minv > d[i] && color[i] != BLACK {
				u = i
				minv = d[i]
			}
		}

		if u == -1 {
			break
		}

		color[u] = BLACK
		for v := 0; v < n; v++ {
			if color[v] != BLACK && (*g)[u][v] != INFTY {
				if d[v] > d[u]+(*g)[u][v] {
					d[v] = d[u] + (*g)[u][v]
					color[v] = GRAY
				}
			}
		}
	}

	var out bytes.Buffer
	for i := 0; i < n; i++ {
		out.WriteString(fmt.Sprintf("%d ", i))
		if d[i] == INFTY {
			out.WriteString(fmt.Sprintf("%d\n", -1))
			continue
		}
		out.WriteString(fmt.Sprintf("%d\n", d[i]))
	}

	return strings.TrimRight(out.String(), "\n")
}

func answer(reader io.Reader) string {
	sc := bufio.NewScanner(reader)
	sc.Split(bufio.ScanWords)

	sc.Scan()
	n, _ := strconv.Atoi(sc.Text())

	g := make(Graph, n)
	for i := 0; i < n; i++ {
		g[i] = make([]int, n)
		for j := 0; j < n; j++ {
			g[i][j] = INFTY
		}
	}

	for i := 0; i < n; i++ {
		sc.Scan()
		u, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		k, _ := strconv.Atoi(sc.Text())

		for j := 0; j < k; j++ {
			sc.Scan()
			v, _ := strconv.Atoi(sc.Text())
			sc.Scan()
			c, _ := strconv.Atoi(sc.Text())

			g[u][v] = c
		}
	}

	return g.dikstra(n)
}

func main() {
	fmt.Println(answer(os.Stdin))
}

C++: #include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<list>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;

const int NIL = -1;
const int MAX = 1 << 21;

int M[101][101];
int color[101], d[101], p[101];

int main(void)
{
	int n, u, k, v, c, mincost;
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			M[i][j] = MAX;
		}
	}
	for (int i = 0; i < n; i++) {
		cin >> u >> k;
		for (int j = 0; j < k; j++) {
			cin >> v >> c;
			M[u][v] = c;
		}
	}
	for (int i = 0; i < n; i++) {
		color[i] = 0;
		d[i] = MAX;
	}
	d[0] = 0;
	p[0] = -1;
	while (1) {
		mincost = MAX;
		for (int i = 0; i < n; i++) {
			if (color[i] != 2 && d[i] < mincost) {
				mincost = d[i];
				u = i;
			}
		}
		if (mincost == MAX)
			break;
		color[u] = 2;
		for (int v = 0; v < n; v++) {
			if (color[v] != 2) {
				if (d[u]+M[u][v] < d[v]) {
					d[v] = M[u][v] + d[u];
					p[v] = u;
					color[v] = 1;
				}
			}
		}
	}
	for (int i = 0; i < n; i++) {
		cout << i << " " << d[i] << endl;
	}
	return 0;
}

C++: #include "bits/stdc++.h"

#define REP(i,num) for(int i=0;i<(num);++i)
#define ALL(c) c.begin(),c.end()
#define PRINTALL(c) for(auto& x:c){cout<<x<<' ';}cout<<endl;
#define PAIRCOMP(c,comp) [](const pair<ll,ll>& lhs,const pair<ll,ll>& rhs){return lhs.c comp rhs.c;}

using namespace std;
using ll = long long;

constexpr ll atcoder_mod = 1e9+7;

template<typename T=int>
T in(){T x; cin >> x; return (x);}
template<typename T=int,typename C=vector<T>>
C vecin(int N){C x(N);REP(i,N){x[i]=in<T>();}return move(x);}

void vout(){cout << endl;}
template<typename Head,typename... Tail>
void vout(Head&& h,Tail&&... t){cout << ' ' << h;vout(forward<Tail>(t)...);}
void out(){cout << endl;}
template<typename Head,typename... Tail>
void out(Head&& h,Tail&&... t){cout << h;vout(forward<Tail>(t)...);}

class Node{
public:
	int color{-1};
	int room{-1};
};

class Edge{
public:
	int start,end;
	int sc,ec;
};

vector<Edge> edge;

class ConnectNodeInfo{
	vector<vector<pair<ll,ll>>> graph;
public:
	ConnectNodeInfo(int node_num){
		graph.resize(node_num);
	}
	void AddNonDirectionalConnection(ll u,ll v,ll w){
		graph[u].emplace_back(v,w);
		graph[v].emplace_back(u,w);
	}
	void AddDirectionalConnection(ll u,ll v,ll w){
		graph[u].emplace_back(v,w);
	}
	vector<pair<ll,ll>>& operator[](ll index){
		return graph[index];
	}
	size_t size(){return graph.size();}
};

bool DFS(vector<Node>& node,ConnectNodeInfo& connect,int index){
	bool result = true;
	int color = node[index].color==1? 0 : 1;
	for(int i=0,ei=connect[index].size();i<ei;i++){
		int connect_index = connect[index][i].first;
		//node[connect_index].color = color;
		if(node[connect_index].color!=-1 && node[connect_index].color==node[index].color){
			return false;
		}
		if(node[connect_index].color==-1){
			Edge e;
			e.start=index,e.end=connect_index;
			edge.emplace_back(e);
			node[connect_index].color = color;
			result &= DFS(node,connect,connect_index);
		}
	}
	return result;
}

class WarshallFloyd{
	vector<vector<ll>> dist;
public:
	void CalcShortestPath(ConnectNodeInfo& connect){
		int V = connect.size();
		dist.resize(V,vector<ll>(V,1LL<<60));

		REP(i,V){
			dist[i][i]=0;
			int U = connect[i].size();
			REP(j,U){
				dist[i][connect[i][j].first] = connect[i][j].second;
			}
		}

		REP(k,V){
			REP(i,V){
				REP(j,V){
					dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
				}
			}
		}
	}
	ll CalcDiameter(){
		ll diameter = -(1LL<<60);
		int V = dist.size();
		REP(i,V){
			REP(j,V){
				if(dist[i][j]<1LL<<60){
					diameter = max(diameter,dist[i][j]);
				}
			}
		}
		return diameter;
	}
	ll GetDistance(int i,int j){
		return dist[i][j];
	}
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N=in();
	ConnectNodeInfo connect(N);
	REP(i,N){
		int u=in(),k=in();
		REP(j,k){
			int v=in(),w=in();
			connect.AddDirectionalConnection(u,v,w);
		}
	}

	WarshallFloyd WF;
	WF.CalcShortestPath(connect);

	REP(i,N){
		out(i,WF.GetDistance(0,i));
	}
	return 0;
}

C++: #include<iostream>
#include<queue>
using namespace std;
const int MAXN=110;
const int INF=1000000000;
struct Node{
	int u,d;
	bool operator < (const Node a) const{
		return this->d<a.d;
	}
	bool operator > (const Node a) const{
		return this->d>a.d;
	}
};
priority_queue<Node ,vector<Node>, greater<Node> > q;
int lowcost[MAXN],used[MAXN];
int n;
int k,v;
int uu;
int map[MAXN][MAXN];
Node mp(int x,int c)
{
	Node tmp;
	tmp.u=x;tmp.d=c;
	return tmp;
}

void input()
{
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>uu>>k;
		for(int j=0;j<k;j++){
		    int c;
	        cin>>v>>c;
	        map[uu][v]=c;
	    }
	}
	for(int i=0;i<n;i++)
	    lowcost[i]=INF;
}

void init()
{
	lowcost[0]=0;
	used[0]=1;
	for(int i=0;i<n;i++)
	    if(map[0][i]) {lowcost[i]=map[0][i];q.push(mp(i,lowcost[i]));}
}

void xxj()
{
	init();
	for(int i=0;i<n-1;i++)
	{
		while(used[q.top().u]) q.pop();
		Node tmp=q.top();q.pop();
		used[tmp.u]=1;
		int ts=tmp.d;
		for(int j=0;j<n;j++)
		{
			if(used[j])continue;
			if(map[tmp.u][j] && map[tmp.u][j]+ts<lowcost[j]) {lowcost[j]=map[tmp.u][j]+ts;q.push(mp(j,lowcost[j]));}
		}
	}
}

void output()
{
	for(int i=0;i<n;i++)
	    cout<<i<<' '<<lowcost[i]<<endl;
}

int main()
{
	input();
	xxj();
	output();
    return 0;
}

C++: #include <iostream>
#define rep(i,N) for(int i = 0; i<(int)(N); i++)
#define REP(i,k,N) for(int i = k; i<(int)(N); i++)
#define INF 100000+1
using namespace std;
const int MAX_N = 10000010;
bool d[MAX_N];
int main(){
        int n;
        cin >> n;
        int d[100][100];
        rep(i,100) rep(j,100) d[i][j]=INF;
        int u,k,v,c;
        rep(i,n){
                cin >> u >>k;
                rep(j,k){
                        cin >> v >> c;
                        d[u][v] = c;
                }
        }

        int l[n];
        rep(i,n) l[i]=INF;
        l[0]=0;
        bool update = true;
        while(update) {
                update  = false;
                rep(from,n) rep(to,n){
                        if(l[to] > l[from]+d[from][to]) {
                                update = true;
                                l[to] = l[from]+d[from][to];
                        }
                }
        }
        rep(i,n){
                cout << i << " " << l[i] << endl;
        }

        return 0;
}