import java.util.Scanner
import java.util.ArrayDeque

fun main(args: Array<String>){
    val sc = Scanner(System.`in`)
    val v = sc.nextInt()
    val graph = AdjacentListGraph(Array(v){ Vertex<Int, Long>(0) }.toMutableList() )
    for (i in 0 until v){
        val u = sc.nextInt()
        val k = sc.nextInt()
        val vs = IntArray(k){ sc.nextInt() }
        vs.forEach{ graph.addEdge(u - 1, it - 1, 1L) }
    }
    val bfs = BreadthFirstSearch(graph, 0)
    bfs.search()
    bfs.distances
        .mapIndexed{ idx, value -> "${idx+1} $value" }
        .joinToString(separator="\n")
        .let{ println(it) }
}


interface Graph<T : Comparable<T>, E : Comparable<E>> {
    val size: Int
    fun getWeight(from: Int, to: Int): E?
    fun edgesFrom(from: Int): List<Edge<E>>
    fun addEdge(from: Int, to: Int, weight: E): Boolean
    fun removeEdge(from: Int, to: Int): Boolean
    fun isAdjacent(from: Int, to: Int): Boolean
}

data class Edge<T : Comparable<T>>(val to: Int, val weight: T)
data class Vertex<T : Comparable<T>, E : Comparable<E>>(val data: T) {
    val edges = mutableListOf<Edge<E>>()

    fun addEdge(to: Int, weight: E) = when (edges.find { it.to == to }) {
        null -> {
            edges.add(Edge(to, weight))
            true
        }
        else -> false
    }

    fun removeEdge(to: Int): Boolean {
        for ((i, edge) in edges.withIndex()) {
            if (edge.to == to) {
                edges.removeAt(i)
                return true
            }
        }
        return false
    }
}

class AdjacentListGraph<T : Comparable<T>, E : Comparable<E>>(
    private val vertices: MutableList<Vertex<T, E>>
) : Graph<T, E> {
    override val size = vertices.size
    override fun getWeight(from: Int, to: Int): E? =
        vertices[from].edges.find { it.to == to }?.weight
    override fun edgesFrom(from: Int): List<Edge<E>> = vertices[from].edges
    override fun addEdge(from: Int, to: Int, weight: E) = vertices[from].addEdge(to, weight)
    override fun removeEdge(from: Int, to: Int) = vertices[from].removeEdge(to)
    override fun isAdjacent(from: Int, to: Int) =
        vertices[from].edges.find { it.to == to } != null
}



class BreadthFirstSearch<T : Comparable<T>>(val graph: Graph<T, Long>, val from: Int) {
    /**
     * Constraints:
     *   - weights must be same
     *
     * Complexity:
     *   - time: O(V)
     *   - space: O(V)
     */

    val distances = Array(graph.size) { -1L }
    val beforeNodes = IntArray(graph.size) { -1 }

    fun search() {
        val deque = ArrayDeque<Int>()
        distances[from] = 0L
        deque.add(from)
        while (deque.size > 0) {
            val node = deque.removeFirst()
            graph.edgesFrom(node).filter { distances[it.to] == -1L }.forEach {
                distances[it.to] = distances[node] + it.weight
                beforeNodes[it.to] = node
                deque.add(it.to)
            }
        }
    }

    fun shortestPath(to: Int): List<Int> {
        val path = ArrayDeque<Int>()
        var current = to
        path.add(to)
        while (current != from) {
            current = beforeNodes[current]
            path.addFirst(current)
        }
        return path.toList()
    }
}

