Go: package main

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

const (
	MAX_N      = 10000
	MAX_WEIGHT = 100000
)

type Edge struct {
	start  int
	end    int
	weight int
}

type ShortestInfo struct {
	edges    []Edge
	shortest int
}

type Neighbor struct {
	node   int
	weight int
}

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

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	shortestList := make([]ShortestInfo, n)
	for i := 1; i < n; i++ {
		shortestList[i] = ShortestInfo{edges: []Edge{}, shortest: MAX_N*MAX_WEIGHT + 1}
	}

	adjacentMatrix, err := createAdjacentMatrix(n, sc)
	if err != nil {
		panic(err)
	}

	sssp([]int{0}, shortestList, adjacentMatrix)
	for _, v := range shortestList {
		fmt.Printf("%d %d\n", v.getEnd(), v.shortest)
	}
}

func (si ShortestInfo) getEnd() int {
	if len(si.edges) == 0 {
		return 0
	} else {
		return si.edges[len(si.edges)-1].end
	}
}

func createAdjacentMatrix(n int, sc *bufio.Scanner) ([][]Neighbor, error) {
	adjacentMatrix := make([][]Neighbor, n)
	for i := 0; i < n; i++ {
		id, err := nextInt(sc)
		if err != nil {
			return nil, err
		}
		adjacentMatrix[id] = []Neighbor{}
		vertexNum, err := nextInt(sc)
		if err != nil {
			return nil, err
		}
		for j := 0; j < vertexNum; j++ {
			v, err := nextInt(sc)
			if err != nil {
				return nil, err
			}
			c, err := nextInt(sc)
			if err != nil {
				return nil, err
			}
			adjacentMatrix[id] = append(adjacentMatrix[id], Neighbor{v, c})
		}
	}
	return adjacentMatrix, nil
}

func sssp(nodeStack []int, shortestList []ShortestInfo, adjacentMatrix [][]Neighbor) {
	for len(nodeStack) > 0 {
		currentNode := nodeStack[0]
		nodeStack = nodeStack[1:]
		currentShortest := getShortest(currentNode, shortestList)
		adjacents := findAdjacents(currentNode, adjacentMatrix)
		for i := 0; i < len(adjacents); i++ {
			adj := adjacents[i]
			if currentShortest.shortest+adj.weight < getShortest(adj.end, shortestList).shortest {
				setShortest(adj.end, adj, currentShortest, shortestList)
				nodeStack = append(nodeStack, adj.end)
			}
		}
	}
}

func getShortest(node int, shortestList []ShortestInfo) ShortestInfo {
	return shortestList[node]
}

func setShortest(node int, edge Edge, currentShortest ShortestInfo, shortestList []ShortestInfo) {
	newEdges := make([]Edge, len(currentShortest.edges)+1)
	for i := 0; i < len(newEdges)-1; i++ {
		newEdges[i] = currentShortest.edges[i]
	}
	newEdges[len(newEdges)-1] = edge
	shortestInfo := ShortestInfo{edges: newEdges, shortest: currentShortest.shortest + edge.weight}
	shortestList[node] = shortestInfo
}

func findAdjacents(currentNode int, adjacentMatrix [][]Neighbor) []Edge {
	adjacents := adjacentMatrix[currentNode]
	edges := []Edge{}
	for _, neighbor := range adjacents {
		edges = append(edges, Edge{start: currentNode, end: neighbor.node, weight: neighbor.weight})
	}
	return edges
}

func nextInt(sc *bufio.Scanner) (int, error) {
	sc.Scan()
	return strconv.Atoi(sc.Text())
}

C++: #include<stdio.h>
#include<stdlib.h>
struct node{
  int key;
  int cost;
  struct node *next;
};
typedef struct node *GG;
  
GG G[10001];
GG MNode(int,int,GG);
void Insert(int,int,int);
int main()
{
  int i,j,n,count=0,v,c,c1,v1;
  int color[10001],d[10001],pi[10001],mincost,ii;
  GG GGG;
  scanf("%d",&n);
  for(i=0;i<n;i++)G[i]=MNode(0,0,NULL);
  for(i=0;i<n;i++){
    scanf("%d%d",&v,&c);
    for(j=0;j<c;j++){
      scanf("%d%d",&v1,&c1);
      Insert(i,v1,c1);
    }
  }
  for(i=0;i<n;i++){
    color[i]=0;
    pi[i]=-1;
    d[i]=10000001;
  }
  d[0]=0;
   
  while(1){
    mincost=10000001;
    for(i=0;i<n;i++){
      if(color[i]!=2 && d[i]<mincost){
        mincost=d[i];
        ii=i;
      }
    }
    if(mincost==10000001)break;
    color[ii]=2;
    for(GGG=G[ii];GGG!=NULL;GGG=GGG->next){
      if(color[GGG->key]!=2 && (GGG->cost+d[ii])<d[GGG->key]){
    pi[GGG->key]=ii;
    d[GGG->key]=GGG->cost+d[ii];
    color[GGG->key]=1;
      }
    }
  }
  for(i=0;i<n;i++)printf("%d %d\n",i,d[i]);
   
  return 0;
}
  
GG MNode(int key,int cost,GG Node)
{
  GG n;
  n=(GG)malloc(sizeof(struct node));
  n->key=key;
  n->cost=cost;
  n->next=Node;
  return n;
}
void Insert(int s,int t,int u)
{
  GG GGG;
  GGG=MNode(t,u,G[s]->next);
  G[s]->next=GGG;
}

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

using namespace std ;
typedef long long ll;
typedef string str;
typedef pair<int, int> pii;
typedef vector<int> vint;
typedef vector<double> vdou ;
typedef vector<ll> vll;
typedef vector<vint> vvint;
typedef vector<str> vstr;
typedef pair<ll,ll> pll ;
typedef vector<pii> vpii ;
typedef vector<pll> vpll ;

#define REP(i, n) for (ll (i) = 0; (i) < (ll)(n); i++) 
#define FOR(i, a, b) for(ll (i) = a; (i) < (ll)b; i++)
#define ALL(v) (v).begin(),(v).end()
#define MOD 1000000007
#define CHI 1000000000000000003
#define NIL -1
#define FI first
#define SE second
#define MP make_pair
#define PB push_back
#define SZ(x)  (ll)x.size()
#define SP(x)  setprecision((ll)x)

const int INF = 1e9;
const ll LINF = 1e18;
const double EPS = 1e-9;
const double PI = M_PI;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;} //最大公約数
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;} //最小公倍数

void yes(){
  cout <<"Yes"<<endl ;
}
void no(){
  cout <<"No"<<endl ;
}
//-----------------------------------------

const int MAX_V = 1e5 ;

struct edge{
    int to, cost ;
    //iからの行き先とそのコストの情報
};

int n ;
vector<edge> G[MAX_V] ;
//G[i]...iからの行き先(to)とコスト(cost)の情報を持つ
int d[MAX_V] ;
//d[i]...sからiへ行くのにかかるコストの最小

int par[MAX_V] ;
//par[i]...iの一個前

void dijkstra(int s){
    priority_queue<pii,vpii,greater<pii> > que ;
    //pair<sからiへ行くのの暫定最小コスト、i>の優先度付きキュー
    REP(i,n){
        d[i] = INF ;
      	par[i] = i ;
        //はじめコストはINFで初期化
    }
    d[s] = 0 ;
    que.push(MP(0,s)) ;
    //自身へのコストは0としてqueへ入れる
    
    while(!que.empty()){
        pii p = que.top() ;
        que.pop() ;
        int v = p.SE ;
        
        if(d[v] < p.FI){
            continue ;
        }
        REP(i,SZ(G[v])){
            //vを経由した行き先について
            edge e = G[v][i] ;
            if(d[e.to]>d[v]+e.cost){
                d[e.to] = d[v] + e.cost ;
                par[v] = e.to ;
                que.push(MP(d[e.to],e.to)) ;
            }
        }
    }
}








//-----------------------------------------
int main()
{
  cin.tie(0);
  ios::sync_with_stdio(false);
  cin >> n ;
  REP(i,n){
      int a, k ;
      cin >> a >> k  ;
      REP(j,k){
          int b, c ;
          cin >> b >> c ;
          edge e = {b,c} ;
          G[a].PB(e) ;
      }
  }
  
  dijkstra(0) ;
  
  REP(i,n){
      cout << i <<" "<<d[i] <<endl;
  }

  return 0 ;
}