数叶子结点

由于给出的是非叶子结点和它对应的子节点,所以采用邻接表的形式来建树
判断叶子结点:h[u] == -1

  1. #include <time.h>
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 110;
  6. int h[N], e[N], ne[N], idx;
  7. int cnt[N], max_depth;
  8. void add(int a, int b) {
  9. e[idx] = b;
  10. ne[idx] = h[a];
  11. h[a] = idx++;
  12. }
  13. void dfs(int u, int depth) {
  14. if (h[u] == -1) {
  15. cnt[depth]++;
  16. max_depth = max(max_depth, depth);
  17. return;
  18. }
  19. for (int i = h[u]; i != -1; i = ne[i]) {
  20. dfs(e[i], depth + 1);
  21. }
  22. }
  23. int main() {
  24. #ifdef SUBMIT
  25. freopen("in.txt", "r", stdin);
  26. freopen("out.txt", "w", stdout);
  27. long _begin_time = clock();
  28. #endif
  29. memset(h, -1, sizeof h);
  30. int n, m;
  31. cin >> n >> m;
  32. while (m--) {
  33. int fa, k;
  34. cin >> fa >> k;
  35. while (k--) {
  36. int id;
  37. cin >> id;
  38. add(fa, id);
  39. }
  40. }
  41. dfs(1, 0);
  42. cout << cnt[0];
  43. for (int i = 1; i <= max_depth; i++)
  44. cout << ' ' << cnt[i];
  45. cout << endl;
  46. #ifdef SUBMIT
  47. long _end_time = clock();
  48. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  49. #endif
  50. return 0;
  51. }

树的遍历

模板:由后序/前序遍历+中序遍历得到层序遍历

  1. #define SUBMIT
  2. #include <time.h>
  3. #include <iostream>
  4. #include <unordered_map>
  5. #include <queue>
  6. using namespace std;
  7. const int N = 40;
  8. int post[N], in[N];
  9. unordered_map<int, int> l, r, pos;
  10. queue<int> q;
  11. int build(int il, int ir, int pl, int pr) {
  12. int root = post[pr];
  13. int k = pos[root];
  14. if (il < k) {
  15. l[root] = build(il, k - 1, pl, pl + k - 1 - il);
  16. }
  17. if (ir > k) {
  18. r[root] = build(k + 1, ir, pl + k - il, pr - 1);
  19. }
  20. return root;
  21. }
  22. void bfs(int root) {
  23. q.push(root);
  24. while (!q.empty()) {
  25. int t = q.front();
  26. q.pop();
  27. if (l.count(t)) q.push(l[t]);
  28. if (r.count(t)) q.push(r[t]);
  29. cout << t;
  30. if (!q.empty()) cout << ' ';
  31. }
  32. }
  33. int main() {
  34. #ifdef SUBMIT
  35. freopen("in.txt", "r", stdin);
  36. freopen("out.txt", "w", stdout);
  37. long _begin_time = clock();
  38. #endif
  39. int n;
  40. cin >> n;
  41. for (int i = 0; i < n; i++) cin >> post[i];
  42. for (int i = 0; i < n; i++) {
  43. cin >> in[i];
  44. pos[in[i]] = i;
  45. }
  46. int root = build(0, n - 1, 0, n - 1);
  47. bfs(root);
  48. #ifdef SUBMIT
  49. long _end_time = clock();
  50. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  51. #endif
  52. return 0;
  53. }

最深的根

一个无环连通图可以被视作一个树,注意是图中是无向边
判断是不是连通图可以看连通分量的个数是否为1,采用并查集
遍历时需要避开父结点,这题不好直接用h[u] == -1来判断根节点,因为相邻的结点至少有父节点

  1. #include <time.h>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <vector>
  5. using namespace std;
  6. const int N = 1e4 + 10, M = N * 2;
  7. int p[N];
  8. int h[N], e[M], ne[M], idx;
  9. void add(int a, int b) {
  10. e[idx] = b;
  11. ne[idx] = h[a];
  12. h[a] = idx++;
  13. }
  14. int find(int x) {
  15. if (x != p[x]) p[x] = find(p[x]);
  16. return p[x];
  17. }
  18. int dfs(int u, int pa) {
  19. int ans = 0;
  20. for (int i = h[u]; i != -1; i = ne[i]) {
  21. if (e[i] != pa) {
  22. ans = max(ans, dfs(e[i], u) + 1);
  23. }
  24. }
  25. return ans;
  26. }
  27. int main() {
  28. #ifdef SUBMIT
  29. freopen("in.txt", "r", stdin);
  30. freopen("out.txt", "w", stdout);
  31. long _begin_time = clock();
  32. #endif
  33. memset(h, -1, sizeof h);
  34. int n;
  35. cin >> n;
  36. int k = n;
  37. for (int i = 1; i <= n; i++) p[i] = i;
  38. for (int i = 0; i < n; i++) {
  39. int a, b;
  40. scanf("%d%d", &a, &b);
  41. add(a, b), add(b, a);
  42. int fa = find(a), fb = find(b);
  43. if (fa != fb) {
  44. p[fa] = fb;
  45. k--;
  46. }
  47. }
  48. if (k > 1) {
  49. printf("Error: %d components", k);
  50. }
  51. else {
  52. vector<int> ans;
  53. int max_depth = -1;
  54. for (int i = 1; i <= n; i++) {
  55. int depth = dfs(i, -1);
  56. if (depth > max_depth) {
  57. max_depth = depth;
  58. ans.clear();
  59. ans.push_back(i);
  60. }
  61. else if (depth == max_depth) {
  62. ans.push_back(i);
  63. }
  64. }
  65. for (auto r: ans) {
  66. printf("%d\n", r);
  67. }
  68. }
  69. #ifdef SUBMIT
  70. long _end_time = clock();
  71. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  72. #endif
  73. return 0;
  74. }

判断二叉搜索树

整数序列从小到大排序的结果就是二叉搜索树中序遍历
判断它是否可能是某个二叉搜索树或其镜像进行前序遍历的结果,就是看能否构建出这样一棵树
若它的右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值,提示我们根节点是第一个遍历到的结点,对于镜像,遍历的方向要反过来

  1. #include <time.h>
  2. #include <iostream>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 1010;
  6. int pre[N], in[N], post[N];
  7. int cnt;
  8. bool build(int il, int ir, int pl, int pr, int type) {
  9. int root = pre[pl];
  10. int k;
  11. if (type == 0) {
  12. for (k = il; k <= ir; k++) {
  13. if (in[k] == root) {
  14. break;
  15. }
  16. }
  17. if (k > ir) return false;
  18. }
  19. else {
  20. for (k = ir; k >= il; k--) {
  21. if (in[k] == root) {
  22. break;
  23. }
  24. }
  25. if (k < il) return false;
  26. }
  27. bool flag = true;
  28. if (il < k) {
  29. flag &= build(il, k - 1, pl + 1, pl + k - il, type);
  30. }
  31. if (ir > k) {
  32. flag &= build(k + 1, ir, pl + k - il + 1, pr, type);
  33. }
  34. post[cnt++] = root;
  35. return flag;
  36. }
  37. void printpost(int n) {
  38. cout << post[0];
  39. for (int i = 1; i < n; i++) {
  40. cout << ' ' << post[i];
  41. }
  42. cout << endl;
  43. }
  44. int main() {
  45. #ifdef SUBMIT
  46. freopen("in.txt", "r", stdin);
  47. freopen("out.txt", "w", stdout);
  48. long _begin_time = clock();
  49. #endif
  50. int n;
  51. cin >> n;
  52. for (int i = 0; i < n; i++) {
  53. cin >> pre[i];
  54. in[i] = pre[i];
  55. }
  56. sort(in, in + n);
  57. if (build(0, n - 1, 0, n - 1, 0)) {
  58. cout << "YES" << endl;
  59. printpost(n);
  60. }
  61. else {
  62. reverse(in, in + n);
  63. cnt = 0;
  64. if (build(0, n - 1, 0, n - 1, 1)) {
  65. cout << "YES" << endl;
  66. printpost(n);
  67. }
  68. else cout << "NO" << endl;
  69. }
  70. #ifdef SUBMIT
  71. long _end_time = clock();
  72. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  73. #endif
  74. return 0;
  75. }

完全二叉搜索树

已知中序遍历,由于是完全二叉树,所以可以唯一确定,进行中序遍历填充树即可
完全二叉树的数组表示就是层序遍历

  1. #include <time.h>
  2. #include <iostream>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 1010;
  6. int a[N], t[N];
  7. int cnt, n;
  8. void dfs(int u) {
  9. if (u * 2 <= n) dfs(u * 2);
  10. t[u] = a[cnt++];
  11. if (u * 2 + 1 <= n) dfs(u * 2 + 1);
  12. }
  13. int main() {
  14. #ifdef SUBMIT
  15. freopen("in.txt", "r", stdin);
  16. freopen("out.txt", "w", stdout);
  17. long _begin_time = clock();
  18. #endif
  19. cin >> n;
  20. for (int i = 0; i < n; i++) cin >> a[i];
  21. sort(a, a + n);
  22. dfs(1);
  23. cout << t[1];
  24. for (int i = 2; i <= n; i++) cout << ' ' << t[i];
  25. cout << endl;
  26. #ifdef SUBMIT
  27. long _end_time = clock();
  28. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  29. #endif
  30. return 0;
  31. }

再次树遍历

使用栈可以以非递归方式实现二叉树的中序遍历
push前面如果也是push,那么该结点就是上面一个结点的左儿子,不然是右儿子
两个儿子表示法即可

  1. #define SUBMIT
  2. #include <time.h>
  3. #include <iostream>
  4. #include <stack>
  5. using namespace std;
  6. const int N = 40;
  7. stack<int> s;
  8. int l[N], r[N];
  9. void dfs(int u, int root) {
  10. if (!u) return;
  11. dfs(l[u], root);
  12. dfs(r[u], root);
  13. cout << u;
  14. if (u != root) cout << ' ';
  15. }
  16. int main() {
  17. #ifdef SUBMIT
  18. freopen("in.txt", "r", stdin);
  19. freopen("out.txt", "w", stdout);
  20. long _begin_time = clock();
  21. #endif
  22. int n;
  23. cin >> n;
  24. int root;
  25. int last = -1;
  26. int type;
  27. for (int i = 0; i < 2 * n; i++) {
  28. string op;
  29. cin >> op;
  30. if (op == "Push") {
  31. int x;
  32. cin >> x;
  33. if (last == -1) {
  34. root = x;
  35. }
  36. else if (type == 0) {
  37. l[last] = x;
  38. }
  39. else {
  40. r[last] = x;
  41. }
  42. type = 0;
  43. last = x;
  44. s.push(x);
  45. }
  46. else {
  47. int t = s.top();
  48. s.pop();
  49. last = t;
  50. type = 1;
  51. }
  52. }
  53. dfs(root, root);
  54. cout << endl;
  55. #ifdef SUBMIT
  56. long _end_time = clock();
  57. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  58. #endif
  59. return 0;
  60. }

完全二叉树

判断完全二叉树的话,考虑数组表示法,下标从1开始计数,这样比较最大下标与结点数目之间的关系,完全二叉树应该是正好n个

  1. #include <time.h>
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 30;
  6. int l[N], r[N];
  7. int has_fa[N];
  8. int maxk, maxid;
  9. void dfs(int u, int k) {
  10. if (u == -1) return;
  11. if (k > maxk) {
  12. maxk = k;
  13. maxid = u;
  14. }
  15. dfs(l[u], k * 2);
  16. dfs(r[u], k * 2 + 1);
  17. }
  18. int main() {
  19. #ifdef SUBMIT
  20. freopen("in.txt", "r", stdin);
  21. freopen("out.txt", "w", stdout);
  22. long _begin_time = clock();
  23. #endif
  24. int n;
  25. cin >> n;
  26. memset(l, -1, sizeof l);
  27. memset(r, -1, sizeof r);
  28. for (int i = 0; i < n; i++) {
  29. string s1, s2;
  30. cin >> s1 >> s2;
  31. if (s1 != "-") {
  32. l[i] = stoi(s1);
  33. has_fa[l[i]] = true;
  34. }
  35. if (s2 != "-") {
  36. r[i] = stoi(s2);
  37. has_fa[r[i]] = true;
  38. }
  39. }
  40. int root = -1;
  41. while (has_fa[++root]);
  42. dfs(root, 1);
  43. if (maxk == n) {
  44. cout << "YES" << ' ' << maxid << endl;
  45. }
  46. else {
  47. cout << "NO" << ' ' << root << endl;
  48. }
  49. #ifdef SUBMIT
  50. long _end_time = clock();
  51. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  52. #endif
  53. return 0;
  54. }

二叉搜索树最后两层结点数量

构建二叉搜索树模板
dfs获取最大深度,记录每个深度对应的结点数目

  1. #include <time.h>
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 1010;
  5. int l[N], r[N], idx, w[N];
  6. int max_depth, num[N];
  7. void insert(int &root, int v) { // root可变
  8. if (!root) {
  9. root = ++idx;
  10. w[root] = v;
  11. return;
  12. }
  13. if (v <= w[root]) insert(l[root], v);
  14. else insert(r[root], v);
  15. }
  16. void dfs(int u, int depth) {
  17. if (!u) return;
  18. num[depth]++;
  19. max_depth = max(max_depth, depth);
  20. dfs(l[u], depth + 1);
  21. dfs(r[u], depth + 1);
  22. }
  23. int main() {
  24. #ifdef SUBMIT
  25. freopen("in.txt", "r", stdin);
  26. freopen("out.txt", "w", stdout);
  27. long _begin_time = clock();
  28. #endif
  29. int n;
  30. cin >> n;
  31. int root = 0;
  32. for (int i = 0; i < n; i++) {
  33. int x;
  34. cin >> x;
  35. insert(root, x);
  36. }
  37. dfs(root, 0);
  38. int n1 = num[max_depth], n2 = num[max_depth - 1];
  39. printf("%d + %d = %d\n", n1, n2, n1 + n2);
  40. #ifdef SUBMIT
  41. long _end_time = clock();
  42. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  43. #endif
  44. return 0;
  45. }

前序和后序遍历

如果只通过前序遍历和后序遍历,则有可能无法确定唯一二叉树
那么枚举前序遍历当中左子树的边界就好了,注意可以没有左子树
中序遍历如果需要右子树来判断合法性,此时使用字符串拼接是个好办法,先暂存左右子树的结果

  1. #include <time.h>
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 40;
  5. int pre[N], post[N];
  6. int dfs(int l1, int r1, int l2, int r2, string &s) {
  7. if (l1 > r1) return 1;
  8. if (pre[l1] != post[r2]) return 0;
  9. int root = pre[l1];
  10. int cnt = 0;
  11. for (int i = l1; i <= r1; i++) { // 可以没有左子树
  12. string l, r;
  13. int lcnt = dfs(l1 + 1, i, l2, l2 + i - l1 - 1, l);
  14. int rcnt = dfs(i + 1, r1, l2 + i - l1, r2 - 1, r);
  15. if (lcnt && rcnt) {
  16. s = l + to_string(root) + ' ' + r; // 中序遍历
  17. cnt += lcnt * rcnt;
  18. }
  19. }
  20. return cnt;
  21. }
  22. int main() {
  23. #ifdef SUBMIT
  24. freopen("in.txt", "r", stdin);
  25. freopen("out.txt", "w", stdout);
  26. long _begin_time = clock();
  27. #endif
  28. int n;
  29. cin >> n;
  30. for (int i = 0; i < n; i++) cin >> pre[i];
  31. for (int i = 0; i < n; i++) cin >> post[i];
  32. string ans;
  33. int cnt = dfs(0, n - 1, 0, n - 1, ans);
  34. if (cnt > 1) {
  35. puts("No");
  36. }
  37. else {
  38. puts("Yes");
  39. }
  40. ans.pop_back();
  41. cout << ans << endl;
  42. #ifdef SUBMIT
  43. long _end_time = clock();
  44. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  45. #endif
  46. return 0;
  47. }

AVL树的根

模板

  1. #include <time.h>
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 30;
  5. int l[N], r[N], h[N], v[N], idx;
  6. int get_balance(int u) {
  7. return h[l[u]] - h[r[u]];
  8. }
  9. void update(int u) {
  10. h[u] = max(h[l[u]], h[r[u]]) + 1;
  11. }
  12. void L(int &u) {
  13. int p = r[u];
  14. r[u] = l[p], l[p] = u;
  15. update(u), update(p);
  16. u = p;
  17. }
  18. void R(int &u) {
  19. int p = l[u];
  20. l[u] = r[p], r[p] = u;
  21. update(u), update(p);
  22. u = p;
  23. }
  24. void insert(int &u, int w) {
  25. if (!u) u = ++idx, v[u] = w;
  26. else if (w < v[u]) {
  27. insert(l[u], w);
  28. if (get_balance(u) == 2) {
  29. if (get_balance(l[u]) == 1) R(u);
  30. else L(l[u]), R(u);
  31. }
  32. }
  33. else {
  34. insert(r[u], w);
  35. if (get_balance(u) == -2) {
  36. if (get_balance(r[u]) == -1) L(u);
  37. else R(r[u]), L(u);
  38. }
  39. }
  40. update(u);
  41. }
  42. int main() {
  43. #ifdef SUBMIT
  44. freopen("in.txt", "r", stdin);
  45. freopen("out.txt", "w", stdout);
  46. long _begin_time = clock();
  47. #endif
  48. int n;
  49. cin >> n;
  50. int root = 0;
  51. while (n--) {
  52. int w;
  53. cin >> w;
  54. insert(root, w);
  55. }
  56. cout << v[root] << endl;
  57. #ifdef SUBMIT
  58. long _end_time = clock();
  59. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  60. #endif
  61. return 0;
  62. }

判断完全 AVL 树

把判断的过程放到层序遍历当中去

  1. #include <time.h>
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 30;
  5. int l[N], r[N], h[N], w[N], idx;
  6. int pos[N * 2];
  7. int q[N], hh, tt = -1;
  8. int n;
  9. int get_balance(int u) {
  10. return h[l[u]] - h[r[u]];
  11. }
  12. void update(int u) {
  13. h[u] = max(h[l[u]], h[r[u]]) + 1;
  14. }
  15. void L(int &u) {
  16. int p = r[u];
  17. r[u] = l[p], l[p] = u;
  18. update(u), update(p);
  19. u = p;
  20. }
  21. void R(int &u) {
  22. int p = l[u];
  23. l[u] = r[p], r[p] = u;
  24. update(u), update(p);
  25. u = p;
  26. }
  27. void insert(int &u, int v) {
  28. if (!u) {
  29. u = ++idx;
  30. w[u] = v;
  31. }
  32. else if (v < w[u]) {
  33. insert(l[u], v);
  34. if (get_balance(u) == 2) {
  35. if (get_balance(l[u]) == 1) R(u);
  36. else L(l[u]), R(u);
  37. }
  38. }
  39. else {
  40. insert(r[u], v);
  41. if (get_balance(u) == -2) {
  42. if (get_balance(r[u]) == -1) L(u);
  43. else R(r[u]), L(u);
  44. }
  45. }
  46. update(u);
  47. }
  48. bool bfs(int root) {
  49. q[++tt] = root;
  50. pos[root] = 1;
  51. bool flag = true;
  52. while (hh <= tt) {
  53. int t = q[hh++];
  54. int p = pos[t];
  55. if (p > n) flag = false;
  56. if (l[t]) {
  57. pos[l[t]] = p * 2;
  58. q[++tt] = l[t];
  59. }
  60. if (r[t]) {
  61. pos[r[t]] = p * 2 + 1;
  62. q[++tt] = r[t];
  63. }
  64. }
  65. return flag;
  66. }
  67. int main() {
  68. #ifdef SUBMIT
  69. freopen("in.txt", "r", stdin);
  70. freopen("out.txt", "w", stdout);
  71. long _begin_time = clock();
  72. #endif
  73. cin >> n;
  74. int root = 0;
  75. for (int i = 0; i < n; i++) {
  76. int v;
  77. cin >> v;
  78. insert(root, v);
  79. }
  80. bool ans = bfs(root);
  81. cout << w[q[0]];
  82. for (int i = 1; i < n; i++) cout << ' ' << w[q[i]];
  83. cout << endl;
  84. if (ans) puts("YES");
  85. else puts("NO");
  86. #ifdef SUBMIT
  87. long _end_time = clock();
  88. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  89. #endif
  90. return 0;
  91. }

判断红黑树

和红黑树关系不大,在建树的过程中递归完成判断即可
注意有可能无法构建出二叉搜索树
权值因为红色结点会变成负数,因此排序的时候要用正数来排

  1. #include <time.h>
  2. #include <iostream>
  3. #include <unordered_map>
  4. #include <algorithm>
  5. using namespace std;
  6. const int N = 40;
  7. int in[N], pre[N];
  8. unordered_map<int, int> pos;
  9. bool ans;
  10. int build(int il, int ir, int pl, int pr, int &sum) {
  11. int root = pre[pl];
  12. int k = pos[abs(root)]; // 用正数判断
  13. if (k < il || k > ir) { // 可能不存在
  14. ans = false;
  15. return 0;
  16. }
  17. int left = 0, right = 0, ls = 0, rs = 0;
  18. if (il < k) {
  19. left = build(il, k - 1, pl + 1, pl + k - il, ls);
  20. }
  21. if (k < ir) {
  22. right = build(k + 1, ir, pl + k - il + 1, pr, rs);
  23. }
  24. if (ls != rs) ans = false;
  25. sum = ls;
  26. if (root < 0) {
  27. if (left < 0 || right < 0) {
  28. ans = false;
  29. }
  30. }
  31. else sum++;
  32. return root;
  33. }
  34. int main() {
  35. #ifdef SUBMIT
  36. freopen("in.txt", "r", stdin);
  37. freopen("out.txt", "w", stdout);
  38. long _begin_time = clock();
  39. #endif
  40. int k;
  41. cin >> k;
  42. while (k--) {
  43. int n;
  44. cin >> n;
  45. for (int i = 0; i < n; i++) {
  46. cin >> pre[i];
  47. in[i] = abs(pre[i]);
  48. }
  49. sort(in, in + n);
  50. pos.clear();
  51. for (int i = 0; i < n; i++) pos[in[i]] = i;
  52. ans = true;
  53. int sum = 0;
  54. int root = build(0, n - 1, 0, n - 1, sum);
  55. if (root < 0) ans = false;
  56. if (ans) puts("Yes");
  57. else puts("No");
  58. }
  59. #ifdef SUBMIT
  60. long _end_time = clock();
  61. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  62. #endif
  63. return 0;
  64. }

中缀表达式

如果结点不是叶子,那么需要加上左右括号

  1. #define SUBMIT
  2. #include <time.h>
  3. #include <iostream>
  4. #include <cstring>
  5. using namespace std;
  6. const int N = 30;
  7. int l[N], r[N], has_fa[N];
  8. bool leaf[N];
  9. string v[N];
  10. string dfs(int u) {
  11. string ls, rs;
  12. if (l[u] != -1) {
  13. ls = dfs(l[u]);
  14. if (!leaf[l[u]]) ls = '(' + ls + ')';
  15. }
  16. if (r[u] != -1) {
  17. rs = dfs(r[u]);
  18. if (!leaf[r[u]]) rs = '(' + rs + ')';
  19. }
  20. return ls + v[u] + rs;
  21. }
  22. int main() {
  23. #ifdef SUBMIT
  24. freopen("in.txt", "r", stdin);
  25. freopen("out.txt", "w", stdout);
  26. long _begin_time = clock();
  27. #endif
  28. memset(l, -1, sizeof l);
  29. memset(r, -1, sizeof r);
  30. int n;
  31. cin >> n;
  32. for (int i = 1; i <= n; i++) {
  33. cin >> v[i] >> l[i] >> r[i];
  34. if (l[i] == -1 && r[i] == -1) leaf[i] = true;
  35. if (l[i] != -1) has_fa[l[i]] = true;
  36. if (r[i] != -1) has_fa[r[i]] = true;
  37. }
  38. int root = 0;
  39. while (has_fa[++root]);
  40. cout << dfs(root);
  41. #ifdef SUBMIT
  42. long _end_time = clock();
  43. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  44. #endif
  45. return 0;
  46. }