Go: package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"strconv"
)

const NIL = -1

type Node struct {
	id     int
	weight int
}

func init() {
	sc.Split(bufio.ScanWords)
}

type NodeHeap []Node

func (h NodeHeap) Len() int           { return len(h) }
func (h NodeHeap) Less(i, j int) bool { return h[i].weight < h[j].weight }
func (h NodeHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *NodeHeap) Push(x interface{}) {
	*h = append(*h, x.(Node))
}

func (h *NodeHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

var sc = bufio.NewScanner(os.Stdin)

func scanInt() int {
	num, _ := strconv.Atoi(scanString())
	return num
}

func scanString() string {
	sc.Scan()
	return sc.Text()
}

func init() {
	sc.Split(bufio.ScanWords)
}

func main() {
	n := scanInt()

	route := make([][]Node, n)
	weight := make([]int, n)
	for i := 0; i < n; i++ {
		weight[i] = NIL
	}

	for i := 0; i < n; i++ {
		u := scanInt()
		k := scanInt()
		route[i] = make([]Node, k)
		for j := 0; j < k; j++ {
			route[u][j] = Node{id: scanInt(), weight: scanInt()}
		}
	}

	start := Node{id: 0, weight: 0}
	h := &NodeHeap{start}
	heap.Init(h)

	for h.Len() > 0 {
		node := heap.Pop(h).(Node)
		if weight[node.id] != NIL {
			continue
		}
		weight[node.id] = node.weight

		for _, nextNode := range route[node.id] {
			if weight[nextNode.id] != NIL {
				continue
			}
			nextNode.weight += node.weight
			heap.Push(h, nextNode)
		}
	}

	for i, w := range weight {
		fmt.Println(i, w)
	}
}

C++: #include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <bitset>
#include <utility>
#include <functional>
#include <numeric>
#include <limits>

template <class T>
using vec = std::vector<T>;

constexpr int nil = -1;
constexpr int inf = std::numeric_limits<int>::max();

struct Edge
{
    int to;
    int cost;

    bool operator<(const Edge& rhs) const
    {
        return cost < rhs.cost;
    }

    bool operator>(const Edge& rhs) const
    {
        return cost > rhs.cost;
    }
};



vec<int> dijkstra(const vec<vec<Edge>>& edges)
{
    using namespace std;

    const int n = edges.size();
    vec<int> distances(n, inf);
    vec<bool> reached(n, false);
    priority_queue<Edge, vector<Edge>, greater<Edge>> pqDist;

    pqDist.push({0, 0});

    while (true)
    {
        //始点からの最短点、コスト
        Edge d {nil, inf};

        //一番近い点を探す
        while (!pqDist.empty())
        {
            auto e = pqDist.top();
            pqDist.pop();

            if (!reached[e.to])
            {
                d = e;
                break;
            }
        }

        if (d.cost == inf)
            break;

        reached[d.to] = true;
        distances[d.to] = d.cost;

        for (auto& e : edges[d.to])
        {
            pqDist.push({e.to, d.cost + e.cost});
        }
    }

    return distances;
}

void solve()
{
    using namespace std;
    int n;
    cin >> n;

    //隣接リスト形式
    vec<vec<Edge>> edges(n);

    //入力
    for (int i = 0; i < n; ++i)
    {
        int v, k;
        cin >> v >> k;
        for (int j = 0; j < k; ++j)
        {
            int to, cost;
            cin >> to >> cost;
            edges[i].push_back({to, cost});
        }
    }

    auto d = dijkstra(edges);

    for (int i = 0; i < n; ++i)
    {
        cout << i << " " << d[i] << endl;
    }
}

int main()
{
    solve();
    return 0;
}

C++: #include <iostream>
#include <queue>
#include <utility>
#include <vector>
using namespace std;
#define MAX 10000
#define INFTY 10000000
#define DEFLT 0
#define WHITE 0
#define GRAY 1
#define BLACK 2

int n;
vector<pair<int, int> > adj[MAX];

void dijkstra(){
  int u, v, d[MAX], color[MAX];
  priority_queue<pair<int, int> > PQ; // uからvへの重みcとuに隣接する頂点の番号vのペア: pair<c, v*(-1)>

  for(int i=0; i<n; i++){
    color[i] = WHITE;
    d[i] = INFTY;
  }
  d[DEFLT] = 0;
  color[0] = GRAY;

  PQ.push(make_pair(0, DEFLT));

  while(!PQ.empty()){
    pair<int, int> f = PQ.top();
    PQ.pop();
    u = f.second;
    color[u] = BLACK;

    for(int i=0; i<adj[u].size(); i++){
      v = adj[u][i].second;
      if(color[v] != BLACK && d[u] + adj[u][i].first < d[v]){
        //cout << "u=" << u << ", v=" << v << ", d[u]=" << d[u] << ", d[v]=" << d[v] << "adj[u][i].first=" << adj[u][i].first << endl;
        d[v] = d[u] + adj[u][i].first;
        color[v] = GRAY;
        PQ.push(make_pair(d[v] * (-1), v));
      }
    }
  }

  for(int i=0; i<n; i++){
    cout << i << " " << d[i] << endl;
  }
}

int main(void){
  int u, k, v, c;
  cin >> n;
  for(int i=0; i<n; i++){
    cin >> u >> k;
    for(int j=0; j<k; j++){
      cin >> v >> c;
      adj[u].push_back(make_pair(c, v));
    }
  }

  dijkstra();
  return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

static const int MAX = 10000;
static const int INFTY = (1 << 20);
static const int WHITE = 0;
static const int GRAY = 1;
static const int BLACK = 2;

int n;

//重み付き有向グラフの隣接リスト表現
vector<pair<int, int>> adj[MAX];


void dijkstra() {
    priority_queue<pair<int, int>> PQ;

    int color[MAX], d[MAX];
    for (int i = 0; i < n; i++) {
        d[i] = INFTY;
        color[i] = WHITE;
    }

    // 0 start
    d[0] = 0;
    PQ.push(make_pair(0, 0));
    color[0] = GRAY;

    while (!PQ.empty()) {
        // choose u
        pair<int, int> f = PQ.top(); // cost, node
        PQ.pop();

        int u = f.second;
        color[u] = BLACK;
        // 最小値を取り出し、それが最短でなければ無視
        if (d[u] < f.first * (-1)) {
            continue;
        }

        for (int j = 0; j < adj[u].size(); j++) {
            int v = adj[u][j].first;
            if (color[v] == BLACK)
                continue;
            
            if (d[v] > d[u] + adj[u][j].second) {
                d[v] = d[u] + adj[u][j].second;

                PQ.push(make_pair(d[v] * (-1), v));
                color[v] = GRAY;
            }
        }
    }

    for (int i = 0; i < n; i++) {
        cout << i << " " << (d[i] == INFTY ? -1 : d[i]) << endl;
    }
}

int main() {
    int k, u, v, c;

    cin >> n;

    for (int i = 0; i < n; i++) {
        cin >> u >> k;
        for (int j = 0; j < k; j++) {
            cin >> v >> c;
            adj[u].push_back(make_pair(v, c));  // node_id, cost
        }
    }

    dijkstra();
}

C++: #include <iostream>
#include <queue>
#include <utility>
#include <vector>

#define MAX_NODE 10000
#define INF 1000000000

using namespace std;

struct Edge {
	int to, w;
	Edge(int to, int w) {
		this->to = to;
		this->w = w;
	}
};
typedef pair<int, int> pii;

vector<Edge> adj[MAX_NODE];
int d[MAX_NODE];

void dijkstra(int n, int start) {
	priority_queue<pii, vector<pii>, greater<pii>> que;
	fill(d, d + n, INF);

	d[start] = 0;
	que.emplace(0, start);
	while (!que.empty()) {
		pii p = que.top();
		que.pop();
		int from = p.second;

		if (d[from] < p.first)
			continue;

		for (auto& e : adj[from])
			if (d[from] + e.w < d[e.to]) {
				d[e.to] = d[from] + e.w;
				que.emplace(d[e.to], e.to);
			}
	}
}

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

	int n;

	cin >> n;

	for (int i = 0; i < n; i++) {
		int u, k;
		cin >> u >> k;
		while (k--) {
			int v, c;
			cin >> v >> c;
			adj[u].emplace_back(v, c);
		}
	}

	dijkstra(n, 0);

	for (int i = 0; i < n; i++)
		cout << i << " " << d[i] << endl;

	return 0;
}