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

C++: #include <cassert>
#include <climits>
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <queue>
#include <set>

/*
?§????????????¢0??§???????¢????
??????????¢????????????????????????¶????????????????????§???????°????????????§??°?????????????????£???????????????????¢????
while(????????????????????????????????§)
    list = ???????????????.Get????°?????????????????????????
    for(list)
        ?????????????????????
*/

class TVertex;
struct TPath
{
    int Cost;
    TVertex* Target;
    TPath(TVertex* ATarget, int ACost)
     : Target(ATarget), Cost(ACost) {}
    bool operator<(const TPath& Right)const
    {
        if(this->Cost  < 0) return false;
        if(Right.Cost < 0) return true;
        return this->Cost < Right.Cost;
    }
    bool operator>(const TPath& Right)const
    {
        return !((*this) < Right);
    }
};
class TVertex
{
    int FIndex;
    std::priority_queue<TPath, std::vector<TPath>, std::greater<TPath> > FList;
    int FDistance;

public:
    TVertex(int Index)
     : FIndex(Index), FDistance(INT_MAX)
    {}
    void Reserve(int Size)
    {
        // FList.reserve(Size);
    }
    void AddPath(const TPath& Path)
    {
        FList.push(Path);
    }
    void SortPath()
    {
        // std::sort(FList.begin(), FList.end(), Compare);
    }
    void PrintDistance(std::ostream& out)const
    {
        out << FIndex << " " << FDistance << std::endl;
    }
    int GetMinCostPath()const
    {
        if(FList.empty()) return INT_MAX;
        return FList.top().Cost + FDistance;
    }
    void PickupMinCostPath(int MinCost, std::list<TPath>& List)
    {
        while(FList.empty() == false && FList.top().Cost + FDistance == MinCost){
            List.push_back(TPath(FList.top().Target, FList.top().Cost + FDistance));
            FList.pop();
        }
    }
    bool SetDistance(int Distance)
    {
        if(FDistance < Distance) return false;
        FDistance = Distance;
        return true;
    }
};
class TGraph
{
    std::vector<TVertex*> FTable;
    std::set<TVertex*> FShortest;
    void Init(int n)
    {
        assert(n > 0);
        FTable.resize(n);
        for(int i = 0; i < n; ++i){
            FTable[i] = new TVertex(i);
        }
    }
    static bool CompareMinCost(const TVertex* Left, const TVertex* Right)
    {
        return Left->GetMinCostPath() < Right->GetMinCostPath();
    }
    void AddShortest(TVertex* Vertex, int Distance)
    {
        if(Vertex->SetDistance(Distance)){
            FShortest.insert(Vertex);
        }
    }
    std::list<TPath> PickupMinCostPath(int MinCost)
    {
        std::list<TPath> Result;
        for(std::set<TVertex*>::const_iterator It = FShortest.begin();
            It != FShortest.end(); ++It)
        {
            (*It)->PickupMinCostPath(MinCost, Result);
        }
        return Result;
    }
    void SetShortest(const std::list<TPath>& MinCostPathList)
    {
        for(std::list<TPath>::const_iterator It = MinCostPathList.begin();
            It != MinCostPathList.end(); ++It)
        {
            AddShortest(It->Target, It->Cost);
        }
    }
public:
    TGraph(int n)
    {
        Init(n);
    }
    void SetupVertex(std::istream& in)
    {
        int Index;
        in >> Index;
        assert(Index >= 0);
        assert(Index < FTable.size());
        int k;
        in >> k;
        FTable[Index]->Reserve(k);
        for(int i = 0; i < k; ++i){
            int v, c;
            in >> v >> c;
            FTable[Index]->AddPath(TPath(FTable[v], c));
        }
        FTable[Index]->SortPath();
    }
    void SearchShortest()
    {
        FTable[0]->SetDistance(0);
        FShortest.insert(FTable[0]);
        while(FShortest.size() != FTable.size()){
            int MinCost = (*std::min_element(FShortest.begin(), FShortest.end(), CompareMinCost))->GetMinCostPath();
            std::list<TPath> PathList = PickupMinCostPath(MinCost);
            SetShortest(PathList);
        }
    }
    void PrintDistance(std::ostream& out)
    {
        for(int i = 0; i < FTable.size(); ++i){
            FTable[i]->PrintDistance(out);
        }
    }
};

int main()
{
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    int n;
    std::cin >> n;
    TGraph Graph(n);
    for(int i = 0; i < n; ++i){
        Graph.SetupVertex(std::cin);
    }
    Graph.SearchShortest();
    Graph.PrintDistance(std::cout);
    return 0;
    
}

C++: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <string>
#include <math.h>
#include <ctype.h>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <functional>
using namespace std;

typedef long long ll;
typedef pair<ll, int> pp;
#define mp(a, b) make_pair(a, b)

struct edge {
	int v, w;
	int next;
	edge() {}
	edge(int v_, int w_, int n_) : v(v_), w(w_), next(n_) {}
};

int n, cnt;
int head[10001];
edge e[600000];
bool vis[10001];
ll dis[10001];

void init()
{
	cnt = 0;
	memset(head, -1, sizeof head);
}
void addedge(int u, int v, int w)
{
	e[++cnt] = edge(v, w, head[u]); head[u] = cnt;
}
void dijkstra(int s)
{
	for (int i = 0; i < n; i++)
		vis[i] = 0, dis[i] = ll(1e18);
	dis[s] = 0; vis[s] = 1;
	for (int i = head[s]; i != -1; i = e[i].next)
		dis[e[i].v] = e[i].w;
	while(1)
	{
		int idx = -1;
		ll dist = 1e18;
		for (int j = 0; j < n; j++)
			if (!vis[j] && dist > dis[j])
			{
				idx = j;
				dist = dis[j];
			}
		if (idx == -1)
			break;
		vis[idx] = 1;
		for (int j = head[idx]; j != -1; j = e[j].next)
		{
			int v = e[j].v;
			ll w = e[j].w;
			if (dis[v] > dis[idx] + w)
				dis[v] = dis[idx] + w, vis[v] = 0;
		}
	}
}

int id[10001];

int main()
{
	int s;
	while (scanf("%d", &n) == 1)
	{
		init();
		for (int i = 0; i < n; i++)
		{
			int u, k;
			scanf("%d%d", &u, &k);
			id[i] = u;
			if (u == 0)
				s = i;
			while (k--)
			{
				int v, w;
				scanf("%d%d", &v, &w);
				addedge(u, v, w);
			}
		}
		dijkstra(s);
		for (int i = 0; i < n; i++)
			printf("%d %lld\n", id[i], dis[i]);
	}
	return 0;
}