#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <stack>
#include <climits>
#include <utility>
#include <cmath>
#include <cstddef>

using namespace std;
typedef long long ll;
#define LN printf("\n")
#define OB printf(" ")
#define rep(i,n,m) for(int  i=n;i<=m;i++)
#define per(i,n,m) for(int i=n;i>=m;i--)
inline void scan(int&x){scanf("%d", &x);}inline void scan(ll&x){scanf("%lld",&x);}inline void scan(double&x){scanf("%lf",&x);}inline void scan(string&x){const char *str;scanf("%s",str);x = string(str);}inline void scan(char&ch){scanf("%c",&ch);}
inline void print(const int&x){printf("%d",x);}inline void print(const ll&x) {printf("%lld",x);}inline void print(const double&x) {printf("%lf",x);}inline void print(const string&x){ const char *str=x.c_str();printf("%s",str);}inline void print(const char&x) {printf("%c",x);}
template<class T> inline void printob(const T&x){print(x);OB;}template<class T> inline void println(const T&x){print(x);LN;}inline void printob(const string&x){const char *str=x.c_str();printf("%s",str); OB;}inline void println(const string&x){const char *str=x.c_str();printf("%s",str); LN;}
template<class T>inline T*scanarray(int&n){T*a=0;scan(n);a=new T[n];if(a==0)exit(1);rep(i,0,n-1){ll tmp;scanf("%lld",&tmp);a[i]=(T)tmp;}return a;}
template<class T>inline void printarray(T*a,int n){if(n==1)println(a[0]);else{rep(i,0,n-2){printob(a[i]);}println(a[n-1]);}}
template<class T>inline T*copyarray(int*a,int n){T*b=0;b=new T[n];if(b==0)exit(1);rep(i,0,n-1)b[i]=a[i];return b;}
/*
scan, print, println    : int, ll, double, string, char
(*)scanarrayはすべての入力の型が同一でないとバグるので注意。 2 5.3 9 8　とかはダメ
stringについては入出力の際はchar*で行い、コード中で便利のためにstringを使えるようにしている
*/
// const ll MaxN = 0;
// ll A[MaxN];
// #define NIL (void*)(-1)

class Tree {

class Node {
    private :
    Node* const NIL = (Node*)-1;

    public :
    int me;
    int parent;
    int left, right;
    Node *parentptr;
    Node *leftptr, *rightptr;

    Node() : Node(-1,-1,-1){
        // println("Node 0 arguments constructor called");
    }
    Node(int me, int left, int right) :
        me(me), parent(-1), left(left), right(right),
        parentptr(NIL),
        leftptr(NIL),
        rightptr(NIL)
    {
        //println("Node 3 arguments constructor called");
    }
    ~Node() {
        delete parentptr;
        delete leftptr;
        delete rightptr;
        parentptr = NIL;
        leftptr = NIL;
        rightptr = NIL;
    }
    int getSibling() {
        int sibling = -1;
        if(parent != -1) {
            if(parentptr->left == me) sibling = parentptr->right;
            else sibling = parentptr->left;
        }
        return sibling;
    }
    int getDegree() {
        int count = 0;
        if(left != -1) count++;
        if(right != -1) count++;
        return count;
    }
    int getDepth(Node* ptr) {
        int count = 0;
        if(ptr->parentptr != NIL) {
            count += getDepth(ptr->parentptr) + 1;
        }
        return count;
    }
    int getHeight(Node* ptr) {
        int count = 0;
        int count1 = 0, count2 = 0;
        if(ptr->leftptr != NIL) {

            count1 += getHeight(ptr->leftptr) + 1;
        }
        if(ptr->rightptr != NIL) {
            count2 += getHeight(ptr->rightptr) + 1;
        }

        return (count1 >= count2) ? count1 : count2;
    }
    void printnode() {
        int sibling = getSibling();
        int degree = getDegree();
        int depth = getDepth(this);
        int height = getHeight(this);
        printf("node %d: parent = %d, sibling = %d, degree = %d, depth = %d, height = %d, ", me, parent, sibling, degree, depth, height);

        if(parent == -1)                    println("root");
        else if(left == -1 && right == -1)  println("leaf");
        else                                println("internal node");
    }

};

    private :
    Node *root;
    int height;
    int nsize;
    Node* *node;
    Node* const NIL = (Node*)-1;

    public :
    Tree(int nsize): nsize(nsize), root(NIL), height(0), node((Node**)NIL) {
        node = new Node*[nsize];
        // println("Tree constructor called");
    }
    ~Tree() {
        // deleteTree(root);
        delete [] node;
        node = (Node**)NIL;
        root = NIL;
    }
    void deleteTree(Node* node) {
        if(node->leftptr != NIL) deleteTree(node->leftptr);
        if(node->rightptr != NIL) deleteTree(node->rightptr);
        delete node;

    }
    void insertNode(int nodeNo, int left, int right) {
        Node *newNode = new Node(nodeNo,left,right);
        node[nodeNo] = newNode;
    }
    void makeTree() {
        //BUILDING TREE
        rep(i,0,nsize-1) {
            if(node[i]->left != -1) {
                // cout << "test1" << endl;
                int left = node[i]->left;
                node[i]->leftptr = node[left];
                node[left]->parentptr = node[i];
                node[left]->parent = node[i]->me;
            }
            if(node[i]->right != -1) {
                // cout << "test2" << endl;
                int right = node[i]->right;
                node[i]->rightptr = node[right];
                node[right]->parentptr = node[i];
                node[right]->parent = node[i]->me;
            }
        }
        //SETTING ROOT
        rep(i,0,nsize-1) {
            if(node[i]->parent == -1) {
                root = node[i];
                break;
            }
        }

    }

    void printAll() {
        rep(i,0,nsize-1) {
            node[i]->printnode();

        }
    }



};

int main() {
    //TEMPLATE
    int n;
    scan(n);
    Tree tree(n);
    if(n>0) {
        rep(i,0,n-1) {
            int nodeNo; scan(nodeNo);
            int left, right; scan(left); scan(right);
            tree.insertNode(nodeNo,left,right);
        }
    }
    tree.makeTree();
    tree.printAll();


    return 0;
}



Measured memory_bytes: 3312