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

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

int *height;
int *calc_parent;
int *relative_weight;

struct Info {
  void set(int arg_parent_id, int arg_weight_sum) {
    parent_id = arg_parent_id;
    weight_sum = arg_weight_sum;
  }
  int parent_id, weight_sum;
};

Info find_parent_and_calc_weight(int id) {
  if (calc_parent[id] == id) {
    Info ret;
    ret.set(id, 0);
    return ret;
  } else {
    Info ret = find_parent_and_calc_weight(calc_parent[id]);
    calc_parent[id] = ret.parent_id;
    relative_weight[id] += ret.weight_sum;
    ret.weight_sum = relative_weight[id];

    return ret;
  }
}

void unite(int a, int b, int w) {

  Info a_info = find_parent_and_calc_weight(a);
  Info b_info = find_parent_and_calc_weight(b);

  if (a_info.parent_id == b_info.parent_id)
    return;

  if (height[a_info.parent_id] == height[b_info.parent_id]) {

    relative_weight[b_info.parent_id] =
        w - (relative_weight[b] - relative_weight[a]);
    calc_parent[b_info.parent_id] = a_info.parent_id;

  } else if (height[a_info.parent_id] == height[b_info.parent_id]) {
    relative_weight[b_info.parent_id] =
        w - (relative_weight[b] - relative_weight[a]);
    calc_parent[b_info.parent_id] = a_info.parent_id;
    height[a_info.parent_id]++;
  } else {

    relative_weight[a_info.parent_id] =
        (relative_weight[b] - relative_weight[a]) - w;
    calc_parent[a_info.parent_id] = b_info.parent_id;
  }
}

bool isSame(int a, int b) {
  Info left = find_parent_and_calc_weight(a);
  Info right = find_parent_and_calc_weight(b);

  return left.parent_id == right.parent_id;
}

int main() {

  int N, M, a, b, w;
  height = new int[100001];
  calc_parent = new int[100001];
  relative_weight = new int[100001];
  char command[2];

  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;

    for (int i = 0; i <= N; i++) {
      height[i] = 0;
      calc_parent[i] = i;
      relative_weight[i] = 0;
    }

    for (int loop = 0; loop < M; loop++) {
      scanf("%s %d %d", command, &a, &b);
      if (command[0] == '!') {
        scanf("%d", &w);
        unite(a, b, w);
      } else {
        if (!isSame(a, b)) {
          printf("UNKNOWN\\n");
        } else {
          printf("%d\\n", relative_weight[b] - relative_weight[a]);
        }
      }
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

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

int *
    parent; //????????°?????????????±?????????????????????????????????????????????????????????¨
int *
    height; //????????°?????????????±?????????????????????????????????????????????????????????¨

int *calc_parent;
int *
    relative_weight; //?????????????????¨??????????????????????????????????????????

int find_parent(int id) {
  if (parent[id] == id)
    return id;
  else {
    return parent[id] = find_parent(parent[id]);
  }
}

int find_calc_parent(int id) {
  if (calc_parent[id] == id)
    return id;
  else {
    // return calc_parent[id] = find_calc_parent(calc_parent[id]);
    return calc_parent[id] = find_calc_parent(
               calc_parent[id]); //?????????????????§??????????????????
  }
}

// calc_parent???????????§????????????
int compress_calc_parent(int id) {
  if (calc_parent[id] == id)
    return id;
  else {
    return calc_parent[id] = find_calc_parent(calc_parent[id]);
  }
}

//??????????????????????????????????¨??????????
int calc_relative_weight(int id) {

  if (calc_parent[id] == id) {
    return 0; //????????????????????????0
  } else {
    // return relative_weight[id] = relative_weight[id] +
    // calc_relative_weight(calc_parent[id]);
    return relative_weight[id] + calc_relative_weight(calc_parent[id]);
  }
}

//??°??????????????±????????????????????????????????¨?????±????????????
void unite(int a, int b, int w) {

  //?????????
  int a_parent = find_parent(a);
  int b_parent = find_parent(b);

  if (a_parent == b_parent)
    return; //????????°???????????????calc_parent??¨?????±??????????????????????????????

  //??±?????????
  if (height[a_parent] == height[b_parent]) {
    parent[b_parent] = a_parent;
    height[a_parent]++;
  } else if (height[a_parent] > height[b_parent]) {
    parent[b_parent] = a_parent;
  } else {
    parent[a_parent] = b_parent;
  }

  int relative_a = calc_relative_weight(a);
  int relative_b = calc_relative_weight(b);

  if ((relative_b - relative_a) - w <=
      0) { // a????????????????????????????????????????????????????????¨???
    // a?????¨???b?????¨???????????????
    relative_weight[calc_parent[b]] = w - (relative_b - relative_a);
    calc_parent[calc_parent[b]] = calc_parent[a];

  } else {
    // b?????¨???a?????¨???????????????
    relative_weight[calc_parent[a]] = (relative_b - relative_a) - w;
    calc_parent[calc_parent[a]] = calc_parent[b];
  }
}

bool isSame(int a, int b) { return find_parent(a) == find_parent(b); }

int main() {

  int N, M, a, b, w;
  parent = new int[100001];
  height = new int[100001];
  calc_parent = new int[100001];
  relative_weight = new int[100001];
  char command[2];

  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;

    for (int i = 1; i <= N; i++) {
      parent[i] = i;
      height[i] = 0;
      calc_parent[i] = i;
      relative_weight[i] = 0; //????????????0???????????????
    }

    for (int loop = 0; loop < M; loop++) {
      scanf("%s %d %d", command, &a, &b);
      if (command[0] == '!') { //??¬?????????
        scanf("%d", &w);
        unite(a, b, w);
      } else { //???????????????
        if (!isSame(a, b)) {
          printf("UNKNOWN\\n");
        } else {
          printf("%d\\n", calc_relative_weight(b) - calc_relative_weight(a));
          // compress_calc_parent(b);
          // compress_calc_parent(a);
        }
      }
    }
  }

  return 0;
}