#include <bits/stdc++.h>
using namespace std;

namespace ext {
	template <class T>
	struct vec_type;
	template <class T>
	constexpr bool is_vec_v;
	using namespace std;
	template<class T>
	struct Vector : std::vector<T> {
		using std::vector<T>::vector;
		char dil = ' ';
		Vector<T> accum() {
			Vector<T> res(this->size() + 1);
			for (size_t i = 0; i < this->size(); i++) {
				res[i+1] = (*this)[i] + res[i];
			}
			return res;
		}
		template<class U = T>
		typename enable_if<is_vec_v<U>, Vector<T>>::type accum2D() {
			const size_t H = this->size();
			const size_t W = (*this)[0].size();
			using S = typename vec_type<U>::type;
			Vector<T> res(H + 1, Vector<S>(W + 1));
			for (size_t i = 0; i < H; i++) {
				for (size_t j = 0; j < W; j++) {
					res[i+1][j+1] = (*this)[i][j];
					res[i+1][j+1] += res[i][j+1];
					res[i+1][j+1] += res[i+1][j];
					res[i+1][j+1] -= res[i][j];
				}
			}
			return res;
		}
		Vector<T> zaatsu() {
			map<T, int> m;
			for (auto& e: *this) m[e] = 1;
			int count = 0;
			for (auto& e: m) e.second = count++;
			Vector<T> res = *this;
			for (auto& e: res) e = m[e];
			return res;
		}
		Vector<T> zaatsu(map<T, int>& r) {
			r.clear();
			map<T, int> m;
			for (auto& e: *this) m[e] = 1;
			int count = 0;
			for (auto& e: m) e.second = count++;
			Vector<T> res = *this;
			for (auto& e: res) r[m[e]] = e, e = m[e];
			return res;
		}
		friend istream& operator>>(istream& is, Vector<T>& t) {
			for (auto& e: t) cin >> e;
			return is;
		}
		friend ostream& operator<<(ostream& os, Vector<T>& t) {
			t.print(' ', os);
			return os;
		}
		void print(char del = ' ', ostream& os = cout) {
			for (size_t i = 0; i < this->size(); i++) {
				os << (*this)[i];
				if (i + 1 != this->size()) os << del;
				os.flush();
			}
		}
		void println(char del = ' ', ostream& os = cout) {
			print(del, os);
			cout << endl;
		}
		long long crossing_merge() {
			auto t = *this;
			return t.crossing_merge_sub();
		}
		// [min_v, max_v)
		long long crossing_bit(T min_v = -1, T max_v = -1) {
			if (min_v == -1) min_v = this->min();
			if (max_v == -1) max_v = this->max() + 1;
			Vector<T> bit(max_v - min_v + 1, 0);
			long long res = 0;
			for (auto e: *this) {
				e = max_v - e;
				for (size_t x = e - 1; x; x -= x & -x) {
					res += bit[x];
				}
				for (size_t x = e; x < bit.size() ; x += x & -x) {
					bit[x]++;
				}
			}
			return res;
		}
		bool permutation() {
			return next_permutation(this->begin(), this->end());
		}
		T& max() {
			return *max_element(this->begin(), this->end());
		}
		T& min() {
			return *min_element(this->begin(), this->end());
		}
private:
		long long crossing_merge_sub() {
			if (this->size() == 1) return 0;
			int x = this->size() / 2;
			Vector<T> left(this->begin(), this->begin() + x);
			Vector<T> right(this->begin() + x, this->end());
			long long res = left.crossing_merge_sub() + right.crossing_merge_sub();
			left.push_back(numeric_limits<T>::max()); right.push_back(numeric_limits<T>::max());
			size_t l = 0, r = 0;
			while (l + r < this->size()) {
				if (left[l] < right[r]) {
					(*this)[l+r] = left[l];
					l++;
				} else {
					(*this)[l+r] = right[r];
					r++;
					res += x - l;
				}
			}
			return res;
		}
	};
	template <class T>
	struct vec_type : std::false_type {};
	template <class T>
	struct vec_type<Vector<T>> : std::true_type {
		using type = T;
	};
	template <class T>
	constexpr bool is_vec_v = vec_type<T>::value;
}
using namespace ext;
using ll = long long;

struct UnionFind {
	int sz;
	vector<int> par;
	UnionFind(int a) : sz(a), par(sz, -1) {}
	int root(int x) { return par[x] < 0 ? x : par[x] = root(par[x]);}
	bool same(int x, int y) { return root(x) == root(y);}
	bool unite(int x, int y) {
		x = root(x);
		y = root(y);
		if (x == y) return false;
		if (size(x) < size(y)) swap(x, y);
		par[x] += par[y];
		par[y] = x;
		return true;
	}
	int size(int x) { return -par[root(x)];}
	int size() { return sz;}
};

int main() {
	int n; cin >> n;
	vector<int> par(n, -1);
	vector<vector<int>> child(n);
	vector<int> sib(n, -1);
	vector<int> height(n);
	
	vector<int> depth(n);
	for (int i = 0; i < n; i++) {
		int v, l, r; cin >> v >> l >> r;
		if (l != -1) par[l] = v, child[v].push_back(l);
		if (r != -1) par[r] = v, child[v].push_back(r);
		if (l != -1 && r != -1) {
			sib[l] = r;
			sib[r] = l;
		}
	}
	int P = -1;
	for (int i = 0; i < n; i++) {
		if (par[i] == -1) P = i;
	}
	auto dfs1 = [&](auto f, int now, int d) -> void {
		depth[now] = d;
		for (auto& x : child[now]) f(f, x, d+1);
	};
	dfs1(dfs1, P, 0);
	auto dfs2 = [&](auto f, int now) -> int {
		for (auto& x : child[now]) height[now] = max(height[now], f(f, x) + 1);
		return height[now];
	};
	dfs2(dfs2, P);
	for (int i = 0; i < n; i++) {
		cout << "node " << i << ": parent = " << par[i] << ", sibling = " << sib[i] << ", degree = " << child[i].size();
		cout << ", depth = " << depth[i] << ", height = " << height[i] << ", ";
		if (par[i] == -1) cout << "root";
		else if ((int) child[i].size() == 0) cout << "leaf";
		else cout << "internal node";
		cout << endl;
	}
}


Measured memory_bytes: 3140