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