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)
	}
}

Python: # -*- coding: utf-8 -*-
from heapq import heapify, heappop, heappush
 
N = int(input())
INF = float("inf")
d = [INF for n in range(N)]
d[0] = 0
adj = [[] for _ in range(N)]
 
searched = [False for _ in range(N)]
searched[0] = True
 
for n in range(N):
    inp = tuple(map(int, input().split()))
    assert n == inp[0]
    adj[n] = list(zip(inp[2::2], inp[3::2]))
 
heap = [[0, 0]]
 
while len(heap):
    pcost, p = heappop(heap)
    searched[p] = True
     
    if d[p] < pcost:
        continue
     
    for v, c in adj[p]:
        if not searched[v]:
            new_cost = pcost + c
            if new_cost < d[v]:
                d[v] = new_cost
                heappush(heap, [new_cost, v])
 
for n in range(N):
    print("{} {}".format(n, d[n]))

Python: import heapq

def main():

    INF = 1000000009
    n = int(input())
    e = [[] for _ in range(n)]
    for i in range(n):
        inf = list(map(int,input().split()))
        for j in range((inf[1])):
            e[inf[0]].append([inf[2+j*2],inf[2+j*2+1]])
    
    dp = [INF]*n
    dp[0] = 0
    pq = [[0,0]]
    heapq.heapify(pq)
    while pq:
        cost,v = heapq.heappop(pq)
        if dp[v]<cost:continue

        for i in range(len(e[v])):
            u = e[v][i][0]
            ncost = cost+e[v][i][1]
            if ncost < dp[u]:
                dp[u] = ncost
                heapq.heappush(pq,[ncost,u])
    for i in range(n):
        print(i,dp[i])


if __name__ == '__main__':
    main()

Python: # -*- coding: utf-8 -*-
from heapq import heappush, heappop

N = int(input())
INF = float("inf")
adj = []
for _ in range(N):
    inp = tuple(map(int, input().split()))
    adj.append(tuple(zip(inp[2::2], inp[3::2])))

checked = [False for _ in range(N)]
d = [float("inf") for _ in range(N)]
d[0] = 0

heap = [[0, 0]] # cost, vec

while heap:
    c, u = heappop(heap)
    if d[u] < c or checked[u]:
        continue
    for nu, nc in adj[u]:
        new_d = d[u] + nc
        if new_d < d[nu]:
            d[nu] = new_d
            heappush(heap, [d[nu], nu])
    checked[u] = True

for n in range(N):
    print("{} {}".format(n, d[n]))

Python: from heapq import heappush, heappop
from typing import List, Tuple
import sys


if __name__ == "__main__":
    num_vertices = int(input())
    adj_list: List[List[Tuple[int, int]]] = [[] for _ in range(num_vertices)]

    for _ in range(num_vertices):
        vertex, adj_num, *adjs = map(lambda x: int(x), input().split())
        for i in range(adj_num):
            # (cost, adj)
            adj_list[vertex].append((adjs[2 * i + 1], adjs[2 * i]))

    distances: List[int] = [sys.maxsize] * num_vertices
    distances[0] = 0
    que: List[Tuple[int, int]] = []
    heappush(que, (0, 0))

    while [] != que:
        base_distance, parent = heappop(que)
        for cost, adj in adj_list[parent]:
            distance = base_distance + cost
            if distance < distances[adj]:
                distances[adj] = distance
                heappush(que, (distance, adj))

    for vertex, distance in enumerate(distances):
        print(f"{vertex} {distance}")

Python: #!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
input:
5
0 3 2 3 3 1 1 2
1 2 0 2 3 4
2 3 0 3 3 1 4 1
3 4 2 1 0 1 1 4 4 3
4 2 2 1 3 3

output:
0 0
1 2
2 2
3 1
4 3
"""

import sys
import heapq as hp

WHITE, GRAY, BLACK = 0, 1, 2


def generate_adj_table(v_table):
    for each in v_table:
        v_index, v_adj_length, *v_adj_list = map(int, each)
        # assert len(v_adj_list) == v_adj_length * 2
        for pair in zip(v_adj_list[::2], v_adj_list[1::2]):
            init_adj_table[v_index][pair[0]] = pair[1]

    return init_adj_table


def dijkstra_path_heap():
    # path search init
    distance[init_vertex] = 0
    path_heap = []
    # heapq: rank by tuple[0], at here it's d[u]
    hp.heappush(path_heap, (0, init_vertex))

    while path_heap:
        current = hp.heappop(path_heap)[1]

        color[current] = BLACK

        for adj, cost in adj_table[current].items():
            if color[adj] is not BLACK:
                # alt: d[u] + w[u,v]
                alt_path = distance[current] + cost
                if alt_path < distance[adj]:
                    # update path_list
                    distance[adj] = alt_path
                    # update heap
                    hp.heappush(path_heap, (alt_path, adj))
                    color[adj] = GRAY
                    parents[adj] = current

    return distance


if __name__ == '__main__':
    _input = sys.stdin.readlines()
    vertices = int(_input[0])
    v_info = map(lambda x: x.split(), _input[1:])
    # assert len(init_vertices_table) == vertices_num

    distance = [float('inf')] * vertices
    parents = [-1] * vertices
    color = [WHITE] * vertices
    init_adj_table = tuple(dict() for _ in range(vertices))
    init_vertex = 0

    adj_table = generate_adj_table(v_info)
    ans = dijkstra_path_heap()
    for i, v in enumerate(ans):
        print(i, v)

Python: # -*- coding: utf-8 -*-
from heapq import heappush, heappop

if __name__ == '__main__':

    n = int(input())
    M = [set() for i in range(n)]

    for i in range(n):
        l = list(map(int, input().split(" ")))
        for k in range(l[1]):
            j = l[2 + 2 * k]
            c = l[2 + 2 * k + 1]
            M[i].add((j, c))

    d = [float("inf")] * n
    h = []

    def dijkstra(s):
        color = [0] * n
        p = [None] * n
        d[s] = 0
        heappush(h, (d[s], s))

        while h:
            _, u = heappop(h)

            color[u] = 2

            for v, c in M[u]:
                if color[v] != 2:
                    if d[u] + c < d[v]:
                        d[v] = d[u] + c
                        color[v] = 1
                        heappush(h, (d[v], v))

    dijkstra(0)
    for i in range(n):
        print(i, d[i])