type NodeId = usize;

#[derive(Debug)]
pub struct Node {
    parent: Option<NodeId>,
    first_child: Option<NodeId>,
    next_brother: Option<NodeId>,
    depth: u32,
}

impl Node {
    fn get_type(&self) -> String {
        if self.depth == 0 {
            return "root".to_owned();
        } else if self.first_child.is_some() {
            return "internal node".to_owned();
        } else {
            return "leaf".to_owned();
        }
    }
}

struct RootedTree {
    nodes: Vec<Node>,
}

impl RootedTree {
    fn n_nodes(&self) -> usize {
        self.nodes.len()
    }

    fn extract_children(&self, id: NodeId) -> Vec<NodeId> {
        match self.nodes[id].first_child {
            Some(id_oldest_child) => {
                let mut brothers = self.extract_brothers(id_oldest_child);
                brothers
            }
            None => Vec::new(),
        }
    }

    fn extract_brothers(&self, id_oldest_child: NodeId) -> Vec<NodeId> {
        let mut brothers = vec![id_oldest_child];
        let mut current = id_oldest_child;

        for _ in 0..self.n_nodes() {
            match self.nodes[current].next_brother {
                Some(id_brother) => {
                    brothers.push(id_brother);
                    current = id_brother;
                }
                None => break,
            }
        }

        brothers
    }

    fn append_node(&mut self, line: Vec<NodeId>) -> () {
        if line.len() < 3 {
            return;
        }

        let node_id = line[0];
        let degree = line[1];
        let mut youngest_child: NodeId = 0;

        for d in 0..degree {
            let child = line[2 + d];
            self.nodes[child].parent = Some(node_id);

            if d == 0 {
                self.nodes[node_id].first_child = Some(child);
            } else {
                self.nodes[youngest_child].next_brother = Some(child);
            }

            youngest_child = child;
        }
    }

    fn fill_depth(&mut self, top: NodeId, depth: u32) {
        self.nodes[top].depth = depth;

        let child = self.nodes[top].first_child;
        if child.is_some() {
            let mut current = child.unwrap();
            loop {
                self.fill_depth(current, depth + 1);
                current = match self.nodes[current].next_brother {
                    Some(id) => id,
                    None => return,
                }
            }
        }
    }

    fn find_root(&self) -> NodeId {
        let mut current = 0 as NodeId;
        loop {
            match self.nodes[current].parent {
                Some(id) => current = id,
                None => return current,
            }
        }
    }
}

fn main() {
    let mut line = String::new();
    std::io::stdin().read_line(&mut line).ok();
    let n = line.trim().parse::<usize>().unwrap();

    let mut nodes: Vec<Node> = Vec::new();
    for _ in 0..n {
        nodes.push(Node {
            parent: None,
            first_child: None,
            next_brother: None,
            depth: 0,
        });
    }

    let mut tree = RootedTree { nodes: nodes };

    for _ in 0..n {
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).ok();
        let inputs: Vec<NodeId> = line.split_whitespace()
            .map(|e| e.parse::<NodeId>().ok().unwrap())
            .collect();

        tree.append_node(inputs);
    }

    let root = tree.find_root();
    tree.fill_depth(root, 0);

    // for (id, node) in tree.nodes.iter().enumerate() {
    //     println!("{} {:?}", id, node);
    // }

    for id_node in 0..n {
        let node = &tree.nodes[id_node];
        println!(
            "node {id}: parent = {parent}, depth = {depth}, {node_type}, {children:?}",
            id = id_node,
            parent = node.parent.map(|x| x as i32).unwrap_or(-1),
            depth = node.depth,
            node_type = node.get_type(),
            children = tree.extract_children(id_node)
        );
    }
}



Measured memory_bytes: 14344