Problem p01884 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

int D = 9901;

struct Hash {
  Hash() {
    hash_value = 0;
    num = 0;
    left_child = right_child = -1;
  }
  ull hash_value;
  ull num, left_child, right_child;
};

struct HashTree {
public:
  void init(int size) {
    hash = new Hash[size];
    num_of_node = 0;
  }

  void addHash(ull value) {
    if (num_of_node == 0) {
      hash[0].hash_value = value;
      hash[0].num = 1;
      num_of_node++;
      return;
    } else {
      int index = 0;

      while (true) {
        if (value == hash[index].hash_value) {
          hash[index].num++;
          return;
        } else if (value > hash[index].hash_value) {
          if (hash[index].right_child == -1) {
            hash[index].right_child = num_of_node;
            hash[num_of_node].hash_value = value;
            hash[num_of_node].num = 1;
            num_of_node++;
            return;
          } else {
            index = hash[index].right_child;
          }
        } else { // value < hash[index].hash_value
          if (hash[index].left_child == -1) {
            hash[index].left_child = num_of_node;
            hash[num_of_node].hash_value = value;
            hash[num_of_node].num = 1;
            num_of_node++;
            return;
          } else {
            index = hash[index].left_child;
          }
        }
      }
    }
  }

  ull calc_ans() {
    ull sum = 0;

    for (int i = 0; i < num_of_node; i++) {
      sum += (hash[i].num) * (hash[i].num - 1) / 2;
    }
    return sum;
  }

  Hash *hash;
  int num_of_node;
};

struct Node {
  vector<int> children;
  int parent;
};

Node *node;
HashTree HT;

ull calc(int node_id) {

  ull Ret = 1;
  ull child;

  for (int i = 0; i < node[node_id].children.size(); i++) {
    child = calc(node[node_id].children[i]);
    Ret = (Ret + child * D) % MOD;
  }

  HT.addHash(Ret);

  return Ret;
}

int main() {

  int N;
  scanf("%d", &N);

  node = (Node *)malloc(sizeof(Node) * (N + 1));
  HT.init(N);

  int parent, child;
  for (int i = 0; i < N - 1; i++) {
    scanf("%d %d", &parent, &child);
    node[parent].children.push_back(child);
    node[child].parent = parent;
  }

  calc(1);

  printf("%lld\\n", HT.calc_ans());

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000001
using namespace std;

struct Hash {
  Hash() {
    hash_value = 0;
    num = 0;
    left_child = right_child = -1;
  }
  ull hash_value;
  ull num, left_child, right_child;
};

struct HashTree {
public:
  void init(int size) {
    hash = new Hash[size];
    num_of_node = 0;
  }

  void addHash(ull value) {
    if (num_of_node == 0) {
      hash[0].hash_value = value;
      hash[0].num = 1;
      num_of_node++;
      return;
    } else {
      int index = 0;

      while (true) {
        if (value == hash[index].hash_value) {
          hash[index].num++;
          return;
        } else if (value > hash[index].hash_value) {
          if (hash[index].right_child == -1) {
            hash[index].right_child = num_of_node;
            hash[num_of_node].hash_value = value;
            hash[num_of_node].num = 1;
            num_of_node++;
            return;
          } else {
            index = hash[index].right_child;
          }
        } else { // value < hash[index].hash_value
          if (hash[index].left_child == -1) {
            hash[index].left_child = num_of_node;
            hash[num_of_node].hash_value = value;
            hash[num_of_node].num = 1;
            num_of_node++;
            return;
          } else {
            index = hash[index].left_child;
          }
        }
      }
    }
  }

  ull calc_ans() {
    ull sum = 0;

    for (int i = 0; i < num_of_node; i++) {
      sum += (hash[i].num) * (hash[i].num - 1) / 2;
    }
    return sum;
  }

  Hash *hash;
  int num_of_node;
};

struct Node {
  vector<int> children;
  int parent;
};

Node *node;
HashTree HT;

vector<int> calc(int node_id) {

  vector<int> Ret;
  Ret.push_back(node[node_id].children.size());

  for (int i = 0; i < node[node_id].children.size(); i++) {
    vector<int> tmp = calc(node[node_id].children[i]);
    for (int k = 0; k < tmp.size(); k++) {
      if (k + 1 >= Ret.size()) {
        Ret.push_back(tmp[k]);
      } else {
        Ret[k + 1] += tmp[k];
      }
    }
  }

  ull pre = 0, current = 0;

  for (int i = 0; i < Ret.size(); i++) {
    current = Ret[i] + pre * MOD;
    pre = current;
  }
  HT.addHash(current);

  return Ret;
}

int main() {

  int N;
  scanf("%d", &N);

  node = (Node *)malloc(sizeof(Node) * (N + 1));
  HT.init(N);

  int parent, child;
  for (int i = 0; i < N - 1; i++) {
    scanf("%d %d", &parent, &child);
    node[parent].children.push_back(child);
    node[child].parent = parent;
  }

  calc(1);

  printf("%lld\\n", HT.calc_ans());

  return 0;
}