Go: package main

import (
	"strconv"
	"fmt"
	"bufio"
	"os"
)
const INF = 1 << 21
var scanner = bufio.NewScanner(os.Stdin)

func nextInt() int {
	scanner.Scan()
	i, e := strconv.Atoi(scanner.Text())
	if e != nil {
		panic(e)
	}
	return i
}


func main() {
	scanner.Split(bufio.ScanWords)
	n := nextInt()
	adj := make([][]int, n)
	for i := range adj {
		adj[i] = make([]int, n)
	}

	for i := 0;i < n; i++ {
		u := nextInt()
		k := nextInt()
		for j := 0; j < k; j++ {
			v := nextInt()
			c := nextInt()
			adj[u][v] = c
		}
	}

	// for i := range adj {
	// 	fmt.Println(adj[i])
	// }

	dist := make([]int, n)
	prev := make([]int, n)
	visited := make([]bool, n)
	dijkstra := func(start int, size int) {
		for i := 0; i < size; i++ {
			dist[i] = INF
			prev[i] = -1
			visited[i] = false
		}
		dist[start] = 0
		for {
			u := -1
			tmp_min := INF
			for i := 0; i < size; i++ {
				if visited[i] == false && dist[i] < tmp_min {
					tmp_min = dist[i]
					u = i
				}
			}
			if u == -1 {
				break
			}
			visited[u] = true
			for i := 0; i < size; i++ {
				if adj[u][i] > 0 {
					w := adj[u][i]
					newlen := dist[u] + w
					if newlen < dist[i] {
						dist[i] = newlen
						prev[i] = u
					}
				}
			}
		}
	}
	dijkstra(0, n)
	for i, cost := range dist {
		fmt.Printf("%d %d\n", i, cost)
	}
}

C++: // 単一始点最短経路 ( ダイクストラ法 )
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>

#include<queue>

using namespace std;

static const int MAX_N = 100;
static const int INFTY = (1 <<21);

static const int NO = 0;
static const int YES = 1;

// グラフ情報を保持する配列
int ary_graph[MAX_N + 1][MAX_N + 1];
// 辺の関係を保持する配列
vector<int> v_connection[MAX_N];
// スタートからの距離を保持する配列
int ary_distance[MAX_N + 1];
// 各頂点の状態を保持する配列 ( 確定 or 未確定 )
int ary_vertex[MAX_N];

void Dijkstra_Method(int start_v, int all_v);

int main(void)
{

    int n, u, k, v, c;

    for(int i = 0; i < MAX_N + 1; i++)
    {
        ary_vertex[i] = NO;

        // 全頂点のスタートからの距離を無限大とする
        ary_distance[i] = INFTY;

        for(int j = 0; j < MAX_N + 1; j++)
        {
            // 配列の初期化
            ary_graph[i][j] = INFTY;
        }
    }

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> u >> k;

        for(int j = 0; j < k; j++)
        {
            cin >> v >> c;

            // 隣接行列の設定
            ary_graph[u][v] = c;
            // 辺の関係の保存
            v_connection[u].push_back(v);
        }
    }

    Dijkstra_Method(0, n);

    // 結果の表示
    for(int i = 0; i < n; i++)
    {
        cout << i << " " << ary_distance[i] << endl;;
    }

    return 0;
}

// ダイクストラ法を実施する関数
// start_v : スタートする頂点のNo.
// all_v   : 全頂点の数
void Dijkstra_Method(int start_v, int all_v)
{

    int ele, confirm_v, tmp_distance;
    int min_distance, min_v;

    bool judge = true;

    // スタート地点の距離はゼロとする
    ary_distance[start_v] = 0;
    // 確定した頂点を設定
    confirm_v = start_v;
    ary_vertex[confirm_v] = YES;

    // 全頂点のスタートからの距離が確定するまで, ループを継続する
    while( judge == true )
    {

        judge = false;
        min_v = INFTY;
        min_distance = INFTY;

        // 確定した頂点から, [直接つながっている] かつ [未確定]の頂点の距離を計算する
        for(int i = 0; i < v_connection[confirm_v].size(); i++)
        {
            // 辺のつながっている頂点No.
            ele = v_connection[confirm_v][i];

            if( ary_vertex[ele] == NO )
            {
                // 未確定の頂点について検討する

                // confirm_v の頂点を経由した場合の距離 ( 経由する頂点までの距離 + 辺の重み )
                tmp_distance = ary_distance[confirm_v] + ary_graph[confirm_v][ele];

                if( tmp_distance < ary_distance[ele] )
                {
                    // 最小値で距離情報を更新する
                    ary_distance[ele] = tmp_distance;
                }

                if( min_distance > tmp_distance )
                {
                    // confirm_v の頂点から, 最小距離の頂点を探す
                    min_distance = tmp_distance;
                    min_v = ele;
                }
            }
        }

        // 次に進むべき頂点の確定
        if( min_v != INFTY )
        {
            confirm_v = min_v;
            ary_vertex[confirm_v] = YES;

            judge = true;
        }
        else
        {
            // 頂点がループ状になってしまった時は, 決定している頂点から最短距離を持つ頂点を探す
            for(int i = 0; i < all_v; i++)
            {
                if( ary_vertex[i] == YES )
                {
                    for(int j = 0; j < v_connection[i].size(); j++)
                    {
                        // iの頂点から, 辺のつながっている頂点No.
                        ele = v_connection[i][j];

                        // 共に確定済みの頂点は除く
                        if( ary_vertex[ele] == NO )
                        {
                            if( min_v > ary_graph[i][ele] )
                            {
                                min_v = ary_graph[i][ele];
                                confirm_v = i;

                                judge = true;
                            }
                        }
                    }
                }
            }
        }
    }

    return;
}

C++: #include <iostream>
#include <vector>
#include <queue>
const int inf=1e9;
using namespace std;
int main(){

  int n,now=0;
  priority_queue < pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > g[100000];
  cin>>n;
  for(int i=0,u,k,v,c;i<n&&cin>>u>>k;i++) for(int j=0;j<k&&cin>>v>>c;j++) g[u].push(make_pair(c,v));
  int flag[100]={},c[100]={};
  for(int i=1;i<n;i++) c[i]=inf;
  for(int i=0;i<n-1;i++){
    int next=g[now].top().second;
    for(;!g[now].empty();g[now].pop()) if(!flag[g[now].top().second]) c[g[now].top().second]=min(c[g[now].top().second],c[now]+g[now].top().first);
    flag[now]=1;
    now=next;
  }
  for(int i=0;i<n;i++) cout<<i<<" "<<c[i]<<endl;
  return 0;

}

C++: #include <stdio.h>
int a[10000][10000];
int d[10000];
int p[10000];
int q[10000];
int main(){
    int n, i, j, t, u, v,c=0;
    scanf("%d", &n);
    for(i = 0; i < n; i++)
        for(j = 0; j < n; j++){
            a[i][j]=1000000000;
            if(i == j) a[i][j] = 0;
        }
    for(i = 0; i < n; i++) {
        scanf("%d", &j);
        scanf("%d", &c);
        for(j = 0; j < c; j++) {
            scanf("%d %d", &t, &u);
            a[i][t] = u;
        }
        d[i] = 1e9;
        q[i] = 0;
    }
    d[0] = 0;
    c = 0;
    while(c != n) {
        t = 0;
        j = 1000000001;
        for(i = 0; i < n;i++) {
            if(!q[i]&&d[i] < j) {
                t = i;
                j = d[i];
            }
        }
        q[t] = 1;c++;
        for(i = 0; i < n; i++) {
            if(a[t][i] != 1000000000) {
                if(d[i] > d[t] + a[t][i]) {
                    d[i] =  d[t] + a[t][i];
                }
            }
        }
    }
    for(i = 0; i < n; i++) {
        printf("%d %d\n", i, d[i]);
    }
    return 0;
}