← Home
```go
package main

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

func main() {
	// Use buffered I/O for efficient reading and writing
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	// Helper function to read the next integer from input
	nextInt := func() int {
		scanner.Scan()
		val, _ := strconv.Atoi(scanner.Text())
		return val
	}

	// Read number of test cases
	if !scanner.Scan() {
		return
	}
	t, _ := strconv.Atoi(scanner.Text())

	for i := 0; i < t; i++ {
		n := nextInt()
		
		// adj[u] stores the list of prerequisites for chapter u
		adj := make([][]int, n+1)
		for u := 1; u <= n; u++ {
			k := nextInt()
			adj[u] = make([]int, k)
			for j := 0; j < k; j++ {
				adj[u][j] = nextInt()
			}
		}

		visited := make([]int, n+1) // 0: unvisited, 1: visiting, 2: visited
		dp := make([]int, n+1)      // dp[u]: minimum passes to understand chapter u
		possible := true

		// DFS function to detect cycles and compute dp values
		var dfs func(int) bool
		dfs = func(u int) bool {
			visited[u] = 1 // Mark as visiting
			maxPass := 1   // Base case: at least 1 pass (if no dependencies)
			
			for _, v := range adj[u] {
				if visited[v] == 1 {
					return false // Cycle detected
				}
				if visited[v] == 0 {
					if !dfs(v) {
						return false
					}
				}
				
				// Calculate pass required given prerequisite v
				// If prerequisite v has index > u, we need to wait for the next pass to read u
				pass := dp[v]
				if v > u {
					pass++
				}
				if pass > maxPass {
					maxPass = pass
				}
			}
			
			visited[u] = 2 // Mark as visited
			dp[u] = maxPass
			return true
		}

		ans := 0
		for u := 1; u <= n; u++ {
			if visited[u] == 0 {
				if !dfs(u) {
					possible = false
					break
				}
			}
			if dp[u] > ans {
				ans = dp[u]
			}
		}

		if possible {
			fmt.Fprintln(writer, ans)
		} else {
			fmt.Fprintln(writer, -1)
		}
	}
}
```