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 <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <map>
using namespace std;

const int WHITE = 0;
const int GRAY = 1;
const int BLACK = 2;

int n;
vector<vector<pair<int,int>>> G;
vector<int> d;
multimap<int,int> pri_m;
vector<int> colors;

//失败了，怀疑是因为相同的cost的情况覆盖了...
void dijkstra(int s){
    d[s] = 0;
    pri_m.insert(make_pair(0,s));

    while(!pri_m.empty()){
        int cost = pri_m.begin()->first;
        int u = pri_m.begin()->second;
        //pri_m.erase(cost);
        map<int,int>::iterator it=pri_m.find(cost);//删除(c,5)
        pair<map<int,int>::iterator,map<int,int>::iterator> pos=pri_m.equal_range(it->first);//利用一对multimap<string,int>指向第一个出现(c,5)的位置和最后一个出现(c,5)的位置
        while (pos.first!=pos.second)
        {
            if (pos.first->second==u)//当pos指向5时
            {
                pos.first=pri_m.erase(pos.first);//删除后会改变pos迭代器，故赋值给自身，指向删除后的下一个键值对
            }
            else
                ++pos.first;//不进行删除操作则自增

        }
        if(d[u] < cost) continue;
        colors[u] = BLACK;
        for(int i = 0;i<G[u].size();i++){
            int v = G[u][i].first;
            if(colors[v] != BLACK){
                if(d[u]+G[u][i].second < d[v]){
                    d[v] = d[u]+G[u][i].second;
                    pri_m.insert(make_pair(d[v],v));
                }
            }
        }
    }
    for(int i=0;i<n;i++) printf("%d %d\n",i,d[i]);
}

int main(){
    //freopen("data.txt","r",stdin);
    cin >> n;
    G.resize(n);
    d.resize(n,INT_MAX);
    colors.resize(n,WHITE);
    int u,k,v,c;
    for(int i = 0;i<n;i++){
        cin >> u >> k;
        for(int j = 0;j<k;j++){
            cin >> v >> c;
            G[u].push_back(make_pair(v,c));
        }
    }
    dijkstra(0);

    return 0;
}

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

using namespace std;
using ll = long long;

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int to, T cost) : to(to), cost(cost){};
};

template <class T = int>
class Graph {
public:
    explicit Graph(int N = 0) : size(N) { path.resize(size); }
    void span(int u, int v, T cost = 1) { path[u].push_back(Edge<T>(v, cost)); }
    vector<Edge<T>> operator[](int v) const { return path[v]; }

    int size;
    vector<vector<Edge<T>>> path;
};

const ll INF = 1LL << 50;

template <class T>
vector<T> dijkstra(const Graph<T>& graph, int s) {
    vector<T> dist(graph.size, INF);
    dist[s] = 0;

    priority_queue<pair<int, T>, vector<pair<int, T>>, greater<pair<int, T>>> que;
    que.push(make_pair(0, s));

    while (!que.empty()) {
        int v;
        T d;
        tie(d, v) = que.top();
        que.pop();
        if (d > dist[v]) continue;

        for (const auto& e : graph[v]) {
            if (dist[e.to] <= dist[v] + e.cost) continue;
            dist[e.to] = dist[v] + e.cost;
            que.push(make_pair(dist[e.to], e.to));
        }
    }
    return dist;
}

int main() {
    int N;
    cin >> N;

    Graph<ll> graph(N);
    for (int i = 0; i < N; ++i) {
        int v, k;
        cin >> v >> k;
        for (int j = 0; j < k; ++j) {
            int sv;
            ll c;
            cin >> sv >> c;
            graph.span(v, sv, c);
        }
    }

    auto dist = dijkstra<ll>(graph, 0);
    for (int v = 0; v < N; ++v) cout << v << " " << dist[v] << endl;
    return 0;
}

C++: #include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef vector<char> VC;
typedef vector<double> VD;
typedef vector<string> VS;
typedef vector<ll> VLL;
typedef vector<PLL> VP;
const static int INF = 1000000000;
const static int MOD = 1000000007;
const int dx[4]={1, 0, -1, 0};
const int dy[4]={0, 1, 0, -1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
#define rep(i,n) for (ll i=0; i<(ll)(n); i++)
#define repd(i,n) for (ll i=n-1; i>=0; i--)
#define rept(i,m,n) for(ll i=m; i<n; i++)
#define stl_rep(itr, x) for (auto itr = x.begin(); itr != x.end(); ++itr)
#define all(x) (x).begin(), (x).end()
#define F first
#define S second
#define PF push_front
#define PB push_back
#define SORT(V) sort((V).begin(), (V).end())
#define RVERSE(V) reverse((V).begin(), (V).end())
#define paired make_pair
#define PRINT(V) for(auto v : (V)) cout << v << " "
//charを整数に
int ctoi(char c) { if (c >= '0' && c <= '9') { return c - '0'; } return 0; }
// 累積和 for (int i = 0; i < N; ++i) s[i+1] = s[i] + a[i]; 
void cum_sum(int N,vector<double> a, vector<double> &s){ for(int i=0; i<N; i++){ s[i+1]=s[i]+a[i];}}
//ユークリッドの控除法
ll gcd(ll a,ll b){
    if(b == 0) return a;
    return gcd(b,a%b);
}
//最小公倍数
ll lcm(ll a,ll b){
    ll g = gcd(a,b);
    return a / g * b; // Be careful not to overflow
}
//素数判定
bool is_prime(long long n) {
    if (n <= 1) return false;
    for (long long p = 2; p * p <= n; ++p) {
        if (n % p == 0) return false;
    }
    return true;
}
int getdigit(ll num){
    unsigned digit=0;
    while(num!=0){
        num /= 10;
        digit++;
    }
    return digit;
}
//空白文字も入力 getline(cin, S);
//桁数指定 setprecision
int n;
vector<vector<pair<int, int>>> G;

void dijkstra(){
    priority_queue<pair<int, int>> PQ;
    int color[10000];
    int d[10000];
    rep(i,n){
        d[i]=INF;
        color[i]=0;
    }
    d[0]=0;
    PQ.push(make_pair(0,0));
    color[0]=1;

    while(!PQ.empty()){
        pair<int, int> f=PQ.top(); PQ.pop();
        int u=f.S;
        color[u]=2;
        if(d[u]<f.F*(-1)) continue;
        rep(j,G[u].size()){
            int v=G[u][j].F;
            if(color[v]==2) continue;
            if(d[v]>d[u]+G[u][j].S){
                d[v]=d[u]+G[u][j].S;
                PQ.push(make_pair(d[v]*-1,v));
                color[v]=1;
            }
        }
    }
    rep(i,n){
        cout << i << " " << (d[i]==INF ? -1 : d[i]) << endl;
    }
}

int main()
{
    ios::sync_with_stdio(0); 
    cin.tie(0); 
    cout.tie(0);
    cin >> n;
    G.resize(n);
    rep(i,n){
        int u,k;
        cin >> u >> k;
        rep(j,k){
            int v,c;
            cin >> v >> c;
            G[u].PB(make_pair(v,c));
        }
    }
    dijkstra();
}