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 "stdc++.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <queue>
//#include "my_gettime.hpp"
//#include "my_random.hpp"
//#include "my_util.hpp"
//using namespace std;

struct Edge{
	Edge(int f, int s, int w){first = f; second = s; weight = w;};
	int first;
	int second;
	int weight;
};

struct NodeP{
	NodeP(){};
	NodeP(int i, int p, int w){id = i; prev = p; weight = w;}
	int id;
	int prev;
	int weight;
	bool operator<(const NodeP & inRhs) const{ return weight < inRhs.weight; }
	bool operator>(const NodeP & inRhs) const{ return weight > inRhs.weight; }
};

#define INF (1<<30)
class Graph{
public:
	Graph(int numnodes);
	//~Graph();
	void addEdge(Edge a);
	void addEdge_nonDirect(Edge e);
	std::vector<NodeP> dijkstra(int start);
	int numNodes;
	//Edge *adj;
	std::vector < std::vector<Edge> > adj;
};
Graph::Graph(int n){
	numNodes = n;
	//adj = (Edge *)malloc(sizeof(Edge)*n*n);
	adj.resize(n);
}
void Graph::addEdge(Edge e){
	//adj[ e.first * numNodes + e.second ] = e;
	adj[e.first].push_back(e);
}
void Graph::addEdge_nonDirect(Edge e){
	adj[e.first].push_back(e);
	Edge e2 = e;
	e2.first = e.second;
	e2.second = e.first;
	adj[e2.first].push_back(e2);
}
std::vector<NodeP> Graph::dijkstra(int start){
	//using P = pair<int , int>;
	int *cost = (int *)malloc(sizeof(int)*numNodes);
	char *flag = (char *)malloc(sizeof(char)*numNodes);
	for(int i=0;i<numNodes;i++) flag[i] = 0;
	for(int i=0;i<numNodes;i++) cost[i] = INF;
	cost[start]=0;
	std::priority_queue < NodeP ,std::vector<NodeP>, std::greater<NodeP> > Q;
	Q.push(NodeP(start,-1, 0));
	std::vector <NodeP> nodeps(numNodes);

	while( !Q.empty() ){
		NodeP node = Q.top();
		Q.pop();
		if( flag[node.id] == 1 ) continue;
		flag[node.id] = 1;
		cost[node.id] = node.weight;

		nodeps[node.id] = node;

		typedef std::vector<Edge>::iterator ITR;
		for( ITR itr = adj[node.id].begin(); itr !=adj[node.id].end(); itr++ ){
			int dis = node.weight + itr->weight;
			if( cost[itr->second] > dis ){
				Q.push(NodeP(itr->second, node.id, dis));
			}
		}

	}

	free(cost);
	free(flag);

	return nodeps;
}

int main(int argc ,char **argv){
	using namespace std;

	int numNodes;
	cin >> numNodes;

	Graph g(numNodes);

	for(int i=0;i<numNodes;i++){
		int nodeid, numedge;
		cin >> nodeid >> numedge;
		for(int j=0;j<numedge;j++){
			int target, weight;
			cin >> target >> weight;
		//	cout<< nodeid<<" "<<target<<" "<<weight<<endl;
			g.addEdge(Edge(nodeid,target,weight));
		}
	}
	vector<NodeP> nodeps = g.dijkstra(0);
	typedef std::vector<NodeP>::iterator ITR;
	for( ITR itr = nodeps.begin(); itr !=nodeps.end(); itr++ ){
		printf("%d %d\n",/*itr->prev,*/itr->id,itr->weight);
	}
	return 0;
}

C++: #include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;

#define NUM 100
#define NIL -1
#define INF 1000000000
#define WHITE 0
#define BLACK 1
int node_num;
vector<tuple<int, int>> G[NUM];
int V[NUM];
int color[NUM];

void init(void){
    scanf("%d", &node_num);

    for(int i = 0; i < node_num; i++){
        int u, k;
        scanf("%d", &u);
        scanf("%d", &k);

        for(int j = 0; j < k; j++){
            int v_, c;
            scanf("%d", &v_);
            scanf("%d", &c);
            G[u].push_back(make_tuple(v_, c));
        }
    }

    for(int i = 0; i < node_num; i++){
        color[i] = WHITE;
        V[i] = INF;
    }
}

void updateAround(int n){
    color[n] = BLACK;
    for(int i = 0; i < G[n].size(); i++){
        V[get<0>(G[n][i])] = min(V[get<0>(G[n][i])], V[n] + get<1>(G[n][i]));
    }

    int min_index = NIL;
    int min_value = INF;
    for(int i = 0; i < node_num; i++){
        if(color[i] == BLACK){
            continue;
        }
        if(V[i] < min_value){
            min_value = V[i];
            min_index = i;
        }
    }
    if(min_index != NIL){
        updateAround(min_index);
    }
}

int main(void){
    init();

    V[0] = 0;
    updateAround(0);

    for(int i = 0; i < node_num; i++){
        printf("%d %d\n", i, V[i]);
    }
}

C++: #include <bits/stdc++.h>
const int INF = 100000;
using namespace std;

int main(void){
  bool used[100];
  int n, G[100][100], p[100];
  cin >> n;
  for(int i=0; i < 100; i++){
    used[i] = false;
    for(int j=0; j < 100; j++){
      G[i][j] = INF;
    }
  }
  for(int i=0; i < n; i++){
    int vtmp, k;cin >> vtmp >> k;
    for(int j=0; j < k; j++){
      int v, c; cin >> v >> c;
      G[vtmp][v] = c; G[v][vtmp] = c;
    }
  }

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

  for(int i=0; i < n; i++){
    int mind = INF;
    int minind;
    for(int j=0; j < n; j++){
      if(used[j] == false && d[j] < mind){
        mind = d[j]; minind = j;
      }
    }
    used[minind] = true;
    for(int j=0; j < n; j++){
      if(used[j] == false && G[minind][j] != INF){
        if(d[minind] + G[minind][j] < d[j]){
          d[j] = d[minind] + G[minind][j];
          p[j] = minind;
        }
      }
    }
  }
  for(int i=0; i < n; i++){
    cout << i << " " << d[i] << endl;
  }

  return 0;
}