Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func nextInt() int {
	n, err := strconv.Atoi(nextString())
	if err != nil {
		fmt.Printf("strconv.Atoi failed: %v\n", err)
	}
	return n
}

func stringifyArray(arr []int) string {
	return strings.TrimRight(fmt.Sprintf("%+v", arr)[1:], "]")
}

var infty = 1000000000

type nodeKey int

type DirectedGraphNode struct {
	key       nodeKey
	adjacents []*DirectedGraphNode
	visited   bool
	d         int
	parent    *DirectedGraphNode
}

type DirectedGraph struct {
	nodes []DirectedGraphNode
}

func (g *DirectedGraph) setAdjacency(l, r nodeKey) {
	g.nodes[l].adjacents = append(g.nodes[l].adjacents, &g.nodes[r])
}

func newDirectedGraph(nNodes int) *DirectedGraph {
	graph := DirectedGraph{}
	graph.nodes = make([]DirectedGraphNode, nNodes)
	for iNodes := 0; iNodes < nNodes; iNodes++ {
		graph.nodes[iNodes].key = nodeKey(iNodes)

		graph.nodes[iNodes].visited = false
		graph.nodes[iNodes].d = infty
		graph.nodes[iNodes].parent = nil
	}
	return &graph
}

type QueueEntry struct {
	node *DirectedGraphNode
	next *QueueEntry
}

type Queue struct {
	head, tail *QueueEntry
}

func (q *Queue) enqueue(node *DirectedGraphNode) {
	entry := QueueEntry{}
	entry.node = node

	if q.tail == nil {
		q.head = &entry
		q.tail = &entry
		return
	}

	q.tail.next = &entry
	q.tail = q.tail.next
}

func (q *Queue) dequeue() *QueueEntry {
	if q.head == nil {
		return nil
	}
	poped := q.head
	q.head = q.head.next
	if q.head == nil {
		q.tail = nil
	}
	return poped
}

func (q *Queue) isEmpty() bool {
	return q.head == nil
}

func fillDistancesByBreadthFirstSearch(g *DirectedGraph, startNode *DirectedGraphNode) {
	startNode.visited = true
	startNode.d = 0

	queue := Queue{}
	queue.enqueue(startNode)
	for !queue.isEmpty() {
		u := queue.dequeue().node
		for _, adjacent := range u.adjacents {
			if !adjacent.visited {
				adjacent.visited = true
				adjacent.d = u.d + 1
				adjacent.parent = u
				queue.enqueue(adjacent)
			}
		}
		u.visited = true
	}
}

func main() {
	scanner.Split(bufio.ScanWords)

	nNodes := nextInt()
	g := newDirectedGraph(nNodes + 1)

	for iNode := 0; iNode < nNodes; iNode++ {
		nodeKeyLeft := nodeKey(nextInt())
		nAdj := nextInt()
		for iAdj := 0; iAdj < nAdj; iAdj++ {
			nodeKeyRight := nodeKey(nextInt())
			g.setAdjacency(nodeKeyLeft, nodeKeyRight)
		}
	}

	// fmt.Println(g)
	fillDistancesByBreadthFirstSearch(g, &g.nodes[1])
	// fmt.Println(g)

	for iNode := 1; iNode <= nNodes; iNode++ {
		node := g.nodes[iNode]
		distance := node.d
		if distance == infty {
			distance = -1
		}
		fmt.Println(node.key, distance)
	}
}

C++: #include<iostream>
#include<list>
#include<vector>
#include<queue>
using namespace std;

void visit(int kyori[], vector<list<int> > adj){
    int k;
    queue<int> que;
    list<int>::iterator t;
    que.push(1);
    while(!que.empty()){
        k = que.front();
        que.pop();
        for(t = adj[k].begin(); t != adj[k].end(); ++t){
            if(kyori[*t] == -1){
                kyori[*t] = kyori[k] + 1;
                que.push(*t);
            }
        }
    }

}

int main(){
    //input
    int n;
    cin >> n;
    int u, k, v;
    int i, j;
    list<int> list_sub;
    vector<list<int> > adj;
    for(i = 0; i <= n; i++){
        adj.push_back(list_sub);
    }
    for(i = 1; i <= n; i++){
        cin >> u >> k;
        for(j = 1; j <= k; j++){
            cin >> v;
            adj[i].push_back(v);
        }
    }

    //calc
    int kyori[n+1];
    for(i = 2; i <= n; i++){
        kyori[i] = -1;
    }
    kyori[1] = 0;
    visit(kyori, adj);

    //answer
    for(i = 1; i <= n; i++){
        cout << i << " " << kyori[i] << endl;
    }
    return 0;
}

C++: #include <iostream>
#include <vector>
#include <queue>
#include <string.h>

using namespace std;

int main(int argc, char* argv[]) {
  int n;
  cin >> n;

  vector<vector<int> > V(n);
  for (int i = 0; i < n; ++i) {
    int u, k;
    cin >> u >> k;
    V[u - 1].resize(k);
    for (int j = 0; j < k; ++j)
      cin >> V[u - 1][j];
  }

  int d[n];
  memset(d, -1, sizeof(int) * n);
  d[0] = 0;

  queue<int> q;
  q.push(0);

  while (!q.empty()) {
    int cur = q.front();
    q.pop();
    for (int i = 0; i < V[cur].size(); ++i) {
      if (d[V[cur][i] - 1] == -1) {
        q.push(V[cur][i] - 1);
        d[V[cur][i] - 1] = d[cur] + 1;
      }
    }
  }

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

  return 0;
}

C++: #include <bits/stdc++.h>
#include <iomanip>
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#define rep(i,x) for(ll i = 0;i<x;i++)
#define all(a) (a).begin(),(a).end()
#define vecin(a) rep(i,a.size())cin >> a[i]
#define vecout(a) rep(i,a.size())cout << a[i] << " ";cout << "\n"
#define vecvec(a) vector<vector<(a)>>
using ll = long long;
using ld = long double;
using namespace std;
using dou = double;
const ll inf = 2147483647;
const ll INF = 1LL << 60;
const ld pi = 3.14159265358;
const ll mod = 1000000007;
typedef pair<ll,ll> P;
using graph = vector<vector<ll>>;
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;}
template<class T> inline bool change(T a,T b){if(a > b){swap(a,b);return true;}return false;}
ll gcd(ll a,ll b){
    if(a < b)swap(a,b);
    if(a % b == 0)return b;
    else return gcd(b,a%b);
}
//素数判定O(sqrt(N))
bool isp(ll n){
    bool res = true;
    if(n == 1)return false;
    else{
        for(ll i = 2;i * i <= n;i++){
            if(n % i == 0){
                res = false;
                break;
            }
        }
        return res;
    }
}
const ll cmax = 1000000;
ll fac[cmax], finv[cmax], inv[cmax];

// テーブルを作る前処理
void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (ll i = 2; i < cmax; i++){
        fac[i] = fac[i - 1] * i % mod;
        inv[i] = mod - inv[mod%i] * (mod / i) % mod;
        finv[i] = finv[i - 1] * inv[i] % mod;
    }
}

// 二項係数計算
ll nCk(ll n, ll k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % mod) % mod;
}
//nのm乗をMODで割ったあまりO(logN)
ll modpow(ll n,ll m,ll MOD){
    ll res = 1;
    while(m){
        if(m & 1)res = (res * n) % MOD;
        m >>= 1;
        n *= n;
        n %= MOD;
    }
    return res;
}

//printf("%.10f\n", N);
/*  vector<ll> vec = {1,2,5,6,8,9,10};
    cout << binary_search(all(vec),5) << endl; -> true*/
/*
    vector<ll> vec = {1,2,5,6,8,9,10};
    auto n = upper_bound(all(vec),4);
    cout << *n << endl; -> 5*/

//    cout << fixed << setprecision(15);

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll N;
    cin >> N;
    graph G(N);
    ll ten,kazu,to;
    rep(i,N){
        cin >> ten;ten--;
        cin >> kazu;
        rep(j,kazu){
            cin >> to;to--;
            G[ten].push_back(to);
        }
    }
    queue<ll> que;
    vector<ll> dist(N,INF);
    dist[0] = 0;
    que.push(0);
    while(que.size()){
        ll n = que.front();que.pop();
        for(auto x : G[n]){
            if(dist[x] == INF){
                que.push(x);
                dist[x] = dist[n] + 1;
            }
        }
    }
    rep(i,N){
        if(dist[i] == INF){
            cout << i + 1 << " " << -1 << endl;
        }
        else cout << i + 1 << " " << dist[i] << endl;
    }
}