package main

/*
根付き木の表現
*/

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

type node struct {
	id       int
	parent   int
	depth    int
	typename string
	child    []int
}

func (n *node) String() string {
	return fmt.Sprintf("node %d: parent = %d, depth = %d, %s, %s", n.id, n.parent, n.depth, n.typename, ints(n.child))
}

func fixParent(tree []*node) *node {
	for _, p := range tree {
		if p == nil {
			continue
		}
		for _, child := range p.child {
			tree[child].parent = p.id
		}
	}
	for _, p := range tree {
		if p != nil && p.parent == -1 {
			return p
		}
	}
	return nil
}
func walkTree(root *node, tree []*node, f func(n *node)) {
	f(root)
	for _, id := range root.child {
		walkTree(tree[id], tree, f)
	}
}
func fixFields(root *node, tree []*node) {
	walkTree(root, tree, func(n *node) {
		switch {
		case n.parent == -1:
			n.typename = "root"
		case len(n.child) == 0:
			n.typename = "leaf"
		case len(n.child) > 0:
			n.typename = "internal node"
		}
		if n.parent != -1 {
			n.depth = tree[n.parent].depth + 1
		}
	})
}
func printNodes(root *node, tree []*node) {
	walkTree(root, tree, func(n *node) {
		fmt.Println(n)
	})
}

func main() {
	const maxnode = 100000
	scanner := makeScanner(8 * 100000)
	n := eGetInt(scanner)
	nodes := make([]*node, maxnode)
	for i := 0; i < n; i++ {
		info := eGetInts(scanner)
		id, child := info[0], info[2:]
		nodes[id] = &node{id: id, parent: -1, child: child}
	}
	root := fixParent(nodes)
	fixFields(root, nodes)
	for i := 0; i < len(nodes); i++ {
		if nodes[i] != nil {
			fmt.Println(nodes[i])
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// ライブラリ
////////////////////////////////////////////////////////////////////////////////
func makeScanner(maxByte int) *bufio.Scanner {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Buffer(make([]uint8, 0, 8192), maxByte)
	return scanner
}
func eGetLine(r *bufio.Scanner) string {
	if r.Scan() {
		return r.Text()
	}
	err := r.Err()
	if err != nil {
		log.Fatal(err)
	}
	// EOF
	return ""
}
func eGetInt(r *bufio.Scanner) int {
	line := eGetLine(r)
	return eAtoi(line)
}
func eGetFields(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Fields(line)
}
func eGetInts(r *bufio.Scanner) []int {
	fields := eGetFields(r)
	ints := make([]int, len(fields))
	for i := 0; i < len(ints); i++ {
		ints[i] = eAtoi(fields[i])
	}
	return ints
}
func eGetChars(r *bufio.Scanner) []string {
	line := eGetLine(r)
	return strings.Split(line, "")
}
func eAtoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		log.Fatal(err)
	}
	return n
}

type ints []int

func (s ints) String() string {
	var buf bytes.Buffer
	buf.WriteString("[")
	sep := ""
	for _, v := range s {
		buf.WriteString(fmt.Sprintf("%s%d", sep, v))
		sep = ", "
	}
	buf.WriteString("]")
	return buf.String()
}

func reverse(a ints) ints {
	r := make(ints, len(a))
	for i := 0; i < len(a); i++ {
		r[i] = a[len(a)-1-i]
	}
	return r
}
func max(a ints) (int, bool) {
	if len(a) == 0 {
		return 0, false
	}
	m := a[0]
	for _, e := range a {
		if e > m {
			m = e
		}
	}
	return m, true
}
func min(a []int) int {
	m := a[0]
	for _, v := range a {
		if v < m {
			m = v
		}
	}
	return m
}

func sum(a ints) int {
	if len(a) == 0 {
		return 0
	}
	sum := 0
	for _, e := range a {
		sum += e
	}
	return sum
}
func find(n int, a ints) int {
	for i, v := range a {
		if n == v {
			return i
		}
	}
	return -1
}



Measured memory_bytes: 23156