Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func nextInt() int {
	n, err := strconv.Atoi(nextString())
	if err != nil {
		fmt.Printf("strconv.Atoi failed: %v\n", err)
	}
	return n
}

var infty = 1000000000

type DirectedGraphNodeID int

type DirectedGraphNode struct {
	key         DirectedGraphNodeID
	adjacents   []*DirectedGraphNode
	costs       []int
	distance    int
	predecessor *DirectedGraphNode
}

func newDirectedGraph(nNodes int) *DirectedGraph {
	graph := DirectedGraph{}
	graph.nodes = make([]*DirectedGraphNode, nNodes)
	for i := 0; i < nNodes; i++ {
		node := DirectedGraphNode{}
		node.key = DirectedGraphNodeID(i)
		node.distance = infty
		graph.nodes[i] = &node
	}
	return &graph
}

type DirectedGraph struct {
	nodes []*DirectedGraphNode
}

func (g *DirectedGraph) setAdjacency(i, j DirectedGraphNodeID, cost int) {
	g.nodes[i].adjacents = append(g.nodes[i].adjacents, g.nodes[j])
	g.nodes[i].costs = append(g.nodes[i].costs, cost)
}

func (g *DirectedGraph) print() {
	for i := 0; i < len(g.nodes); i++ {
		node := g.nodes[i]
		key := node.key
		strings := []string{strconv.Itoa(int(key)), strconv.Itoa(node.distance)}
		for j := 0; j < len(node.adjacents); j++ {
			nodeJ := fmt.Sprintf("(%v, %v)", node.adjacents[j].key, node.costs[j])
			strings = append(strings, nodeJ)
		}
		fmt.Printf("%v\n", strings)
	}
}

func (g *DirectedGraph) relaxEdge(l, r *DirectedGraphNode, w int) {
	if r.distance > l.distance+w {
		// fmt.Printf("%v -> %v, %v\n", l.key, r.key, l.distance+w)
		r.distance = l.distance + w
		r.predecessor = l
	}
}

func main() {
	scanner.Split(bufio.ScanWords)

	nNodes := nextInt()
	graph := newDirectedGraph(nNodes)

	for i := 0; i < nNodes; i++ {
		iNode := DirectedGraphNodeID(nextInt())
		nAdjacent := nextInt()
		for j := 0; j < nAdjacent; j++ {
			jNode := DirectedGraphNodeID(nextInt())
			cost := nextInt()
			graph.setAdjacency(iNode, jNode, cost)
		}
	}

	graph.nodes[0].distance = 0
	for iNode := 0; iNode < nNodes; iNode++ {
		for iLeft := 0; iLeft < len(graph.nodes); iLeft++ {
			nodeLeft := graph.nodes[iLeft]
			for iRight := 0; iRight < len(nodeLeft.adjacents); iRight++ {
				nodeRight := nodeLeft.adjacents[iRight]
				cost := nodeLeft.costs[iRight]
				graph.relaxEdge(nodeLeft, nodeRight, cost)
			}
		}
	}

	// graph.print()

	for iNode := 0; iNode < len(graph.nodes); iNode++ {
		node := graph.nodes[iNode]
		fmt.Println(node.key, node.distance)
	}
}

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;
}