Go: package main

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

type Node struct {
	Id int
	Dis int
}

type PriorityQueue []*Node

func (pq PriorityQueue) Len() int { return len(pq) }

func (pq PriorityQueue) Less(i, j int) bool {
	return pq[i].Dis < pq[j].Dis
}

func (pq PriorityQueue) Swap(i, j int) {
	pq[i], pq[j] = pq[j], pq[i]
}

func (pq *PriorityQueue) Push(x interface{}) {
	*pq = append(*pq, x.(*Node))
}

func (pq *PriorityQueue) Pop() interface{} {
	n := len(*pq)
	pop := (*pq)[n-1]
	*pq = (*pq)[0:n-1]
	return pop
}

func main() {
	var n int
	fmt.Scan(&n)

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

	g := make([][]int, n)
	c := make([][]int, n)
	pq := make(PriorityQueue, 0, n)
	d := make([]int, n)
	for i := 0; i < n; i++ {
		sc.Scan()
		u, _ := strconv.Atoi(sc.Text())
		sc.Scan()
		k, _ := strconv.Atoi(sc.Text())
		g[u] = make([]int, k)
		c[u] = make([]int, k)
		for j := 0; j < k; j++ {
			sc.Scan()
			g[u][j], _ = strconv.Atoi(sc.Text())
			sc.Scan()
			c[u][j], _ = strconv.Atoi(sc.Text())
		}

		if u == 0 {
			d[u] = 0
		} else {
			d[u] = 1 << 30
		}
		pq.Push(&Node{u, d[u]})
	}
	heap.Init(&pq)

	for pq.Len() > 0 {
		node := heap.Pop(&pq).(*Node)
		for i := 0; i < len(g[node.Id]); i++ {
			nextId := g[node.Id][i]
			nextDis := node.Dis + c[node.Id][i]
			if nextDis < d[nextId] {
				d[nextId] = nextDis
				heap.Push(&pq, &Node{nextId, nextDis})
			}
		}
	}

	wr := bufio.NewWriter(os.Stdout)
	for i := 0; i < n; i++ {
		wr.WriteString(strconv.Itoa(i))
		wr.WriteString(" ")
		wr.WriteString(strconv.Itoa(d[i]))
		wr.WriteString("\n")
	}
	wr.Flush()
}

Python: from heapq import*
n=int(input())
A=[[]for _ in[0]*n]
for _ in[0]*n:
 e=list(map(int,input().split()))
 for i in range(e[1]):k=2*-~i;A[e[0]]+=[(e[k],e[k+1])]
H=[[0,0]]
d=[0]+[1e6]*n
c=[1]*n
while H:
 f=heappop(H)
 u=f[1]
 c[u]=0
 if d[u]>=f[0]:
  for s in A[u]:
   v=s[0]
   if c[v]and d[v]>d[u]+s[1]:
    d[v]=d[u]+s[1]
    heappush(H,[d[v],v])
for i in range(n):print(i,d[i])

Python: import heapq
from collections import deque
from enum import Enum
import sys
import math
from _heapq import heappush, heappop
import copy
from test.support import _MemoryWatchdog

BIG_NUM = 2000000000
HUGE_NUM = 99999999999999999
MOD = 1000000007
EPS = 0.000000001
sys.setrecursionlimit(100000)


class Edge:
    def __init__(self,arg_to,arg_dist):
        self.to = arg_to
        self.dist = arg_dist

class Info:
    def __init__(self,arg_node_id,arg_sum_dist):
        self.node_id = arg_node_id
        self.sum_dist = arg_sum_dist

    def __lt__(self,another):
        return self.sum_dist < another.sum_dist


V = int(input())
G = [[] for _ in range(V)] #隣接グラフ
min_dist = [BIG_NUM]*V

for _ in range(V):
    node_id,num_adj,*tmp_array = list(map(int,input().split()))
    for i in range(0,len(tmp_array),2):
        G[node_id].append(Edge(tmp_array[i],tmp_array[i+1]))

min_dist[0] = 0
Q = []
heappush(Q, Info(0,0))

while len(Q) > 0:
    info = heappop(Q)
    if info.sum_dist > min_dist[info.node_id]:continue
    for e in G[info.node_id]:
        if min_dist[e.to] > info.sum_dist+e.dist:
            min_dist[e.to] = info.sum_dist+e.dist
            heappush(Q, Info(e.to,min_dist[e.to]))

for i in range(V):
    print("%d %d"%(i,min_dist[i]))

Python: import sys
from heapq import*
e=sys.stdin.readline
I=float("inf")
def m():
 n=int(e())
 A=[]
 for _ in[0]*n:
  b=list(map(int,e().split()))
  A+=[zip(b[2::2],b[3::2])]
 d=[0]+[I]*n
 H=[(0,0)]
 while H:
  u=heappop(H)[1]
  for v,c in A[u]:
   t=d[u]+c
   if d[v]>t:
    d[v]=t
    heappush(H,(t,v))
 print('\n'.join(f'{i} {d[i]}'for i in range(n)))
m()

Python: def dijkstra(n):
    inf = 10 ** 6 + 1
    dist = [0] + [inf] * (n - 1)
    visited = [False] * n

    while not all(visited):
        dmin = inf
        for i, (d, v) in enumerate(zip(dist, visited)):
            if dmin > d and not v:
                dmin, u = d, i
        visited[u] = True
        for (v, c) in edge[u]:
            if dist[v] > dist[u] + c:
                dist[v] = dist[u] + c
    return dist

n = int(input())
edge = [[]] * n
for _ in range(n):
    l = list(map(int, input().split()))
    edge[l[0]] = (e for e in zip(l[2::2], l[3::2]))
for i, c in enumerate(dijkstra(n)):
    print(i, c)

Python: # -*- coding: utf-8 -*-

import sys
from heapq import heappush, heappop

sys.setrecursionlimit(10 ** 9)
def input(): return sys.stdin.readline().strip()
def INT(): return int(input())
def MAP(): return map(int, input().split())
def LIST(): return list(map(int, input().split()))
INF=float('inf')

# ダイクストラ(頂点数, 隣接リスト(0-indexed), 始点)
def dijkstra(N: int, nodes: list, src: int) -> list:
    # 頂点[ある始点からの最短距離]
    # (経路自体を知りたい時はここに前の頂点も持たせる)
    res = [float('inf')] * N
    # スタート位置
    que = [(0, src)]
    res[src] = 0
    # キューが空になるまで
    while len(que) != 0:
        # srcからの距離, 現在のノード
        dist, cur = heappop(que)
        # 出発ノードcurの到着ノードでループ
        for nxt, cost in nodes[cur]:
            # 今回の経路のが短い時
            if res[cur] + cost < res[nxt]:
                res[nxt] = res[cur] + cost
                # 現在の移動距離をキューの優先度として、早い方から先に処理するようにする
                heappush(que, (res[nxt], nxt))
    # ノードsrcからの最短距離リストを返却
    return res

N=INT()
nodes=[[] for i in range(N)]
for i in range(N):
    l=LIST()
    u=l[0]
    k=l[1]
    l=l[2:]
    for j in range(0, k*2, 2):
        nodes[u].append((l[j], l[j+1]))

ans=dijkstra(N, nodes, 0)
for i in range(N):
    print(i, ans[i])