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

Python: from collections import deque
N = int(input())
g = {i: deque() for i in range(1,N+1)} #1-index
for i in range(1, N+1):
    u, k, *v = map(int, input().split())
    for j in v:
        g[u].append(j)
        
seen = [0]*(N+1) #1-index
que = deque([])
dist = [-1]*(N+1) #1-index

seen[1] = 1
que.append(1)
dist[1] = 0

while que: #queが空になるまで
    q_no = que.popleft()
    if not g[q_no]: continue #点q-noから他の点に伸びていない
    
    for next_v in g[q_no]:
        if seen[next_v] == 1: continue #訪問済
        
        seen[next_v] = 1 #訪問済にする
        dist[next_v] = dist[q_no] + 1 #距離情報を格納
        que.append(next_v) #queに追加

for i in range(1, N+1):
    print(i, dist[i])

Python: from collections import deque
n=int(input())
l=[0]+[list(map(int,input().split()))[2:] for _ in range(n)]

flg=["white"]*(n+1)
dist=[-1]*(n+1)

def BFS(x):

    queue = deque([x])
    dist[x]=0
    flg[x]="gray"

    while queue:
        current=queue.popleft()
        for i in l[current]:
            if flg[i]=="white":
                queue.append(i)
                flg[i]="gray"
                dist[i]=dist[current]+1
        flg[current]="black"

BFS(1)

for num,i in enumerate(dist[1:],1):
    print(num,i)

Python: import queue
N=int(input())
M=[input().split()[2:]for _ in[0]*N]
q=queue.Queue();q.put(0)
d=[-1]*N;d[0]=0
while not q.empty():
 u=q.get()
 for v in M[u]:
  v=int(v)-1
  if d[v]<0:d[v]=d[u]+1;q.put(v)
for i in range(N):print(i+1,d[i])

Python: cin = open(0).read().strip().split('\n')
n = int(cin[0])
v = [list(map(lambda x: int(x)-1, a.split(' ')[2:])) for a in cin[1:]]

import queue
q = queue.Queue()
q.put(0)

dist = [-1]*n
dist[0] = 0
seen = [False]*n
while not q.empty():
    num = q.get()
    seen[num] = True
    for a in v[num]:
        if dist[a] != -1: continue
        dist[a] = dist[num] + 1
        q.put(a)

for idx, num in enumerate(dist):
    print(idx+1, num)

Python: import sys
import queue
readline = sys.stdin.readline
write = sys.stdout.write

n = int(input())
G = [None for i in range(n+1)]
dist = [-1,]*(n+1)
for i in range(n):
    node_id, k, *adj = map(int, readline().split())
    # adj.sort()
    G[node_id] = adj

def bfs(G):
    #q1が空でなければcntをインクリメントして下のブロックの処理を行う
        #q1から要素取り出し
        #→既に見た節点ならばそれに対しては処理を行わずq1から要素を取り出す(節点1⇔節点2の時の無限ループ回避)
        #→最短距離を格納した後,その要素の子をq2に入れる
        #→q1から要素が無くなったらq2の要素を全てq1に入れる
    cnt = -1

    q1 = queue.Queue()
    q2 = queue.Queue()
    q1.put(1)
    while not q1.empty():
        cnt += 1
        while not q1.empty():
            val = q1.get()
            if dist[val] != -1:
                continue
            dist[val] = cnt
            listlen = len(G[val])
            for i in range(listlen):
                q2.put(G[val][i])
        while not q2.empty():
            q1.put(q2.get())
bfs(G)
for i in range(1, n+1):
    write(str(i) + " " + str(dist[i]) + "\n")

Python: import queue
N=int(input())
M=[input().split()[2:]for _ in[0]*N]
q=queue.Queue();q.put(0)
d=[-1]*N;d[0]=0
while q.qsize()>0:
 u=q.get()
 for v in M[u]:
  v=int(v)-1
  if d[v]<0:d[v]=d[u]+1;q.put(v)
for i in range(N):print(i+1,d[i])

Python: def BFS(s, r):
    d[s] = r
    for i in range(1, n+1):
        if G[s][i] == 1 and flag[i] == 0:
            BFS(i, r+1)

n = int(raw_input())
G = [[0 for i in range(n+1)] for j in range(n+1)]
d = [-1 for i in range(n+1)]

for i in range(n):
    v = map(int, raw_input().split())
    for j in range(v[1]):
        G[v[0]][v[2+j]] = 1

flag = [0 for i in range(n+1)]
BFS(1, 0)

for i in range(1, n+1):
    print(str(i) + " " + str(d[i]))

Python: n = int(raw_input())

G = [0 for i in range(n)] 
a = [[0 for i in range(n)] for j in range(n)]
dis = [-1 for i in range(n)]

for i in range(n):
    G = map(int, raw_input().split())
    for j in range(G[1]):
        a[G[0]-1][G[2+j]-1] = 1

def bfs_visit(s):
    for k in range(n):
      if a[s][k] == 1 and dis[k] == -1:
         dis[k] = dis[s] + 1
         bfs_visit(k)

for s in range(s):
    bfs_visit()
for s in range(s):
    print (s+1,dis[s])

Python: import sys
from collections import deque

n = int(sys.stdin.readline().strip())
edges = [[] for _ in range(n)]
for _ in range(n):
    tmp = list(map(int, sys.stdin.readline().strip().split(" ")))
    for node in tmp[2:]:
        edges[tmp[0] - 1].append(node-1)
# print(edges)

distance = [0] * n
q = deque()
q.append((0, 0))
visited = set()
while q:
    node, d = q.popleft()
    # print(node, d)
    if node in visited:
        continue
    distance[node] = d
    visited.add(node)
    for next in edges[node]:
        # print("next", next)
        q.append((next, d + 1))

for i, d in enumerate(distance):
    if i == 0:
        print(1, 0)
    else:
        print(i + 1, d if d > 0 else -1)