Problem p00909 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cstdio>
#include <iostream>
using namespace std;
#define MAX_N 100

class union_find {
private:
  int parents[MAX_N];
  int rank[MAX_N];
  int weight[MAX_N];

public:
  union_find() {
    for (int i = 0; i < MAX_N; i++) {
      parents[i] = i;
      rank[i] = 0;
      weight[i] = 0;
    }
  }
  union_find(int n) {
    for (int i = 0; i < n; i++) {
      parents[i] = i;
      rank[i] = 0;
      weight[i] = 0;
    }
  }
  int find(int x) {
    if (parents[x] == x) {
      return x;
    } else {
      int tmp = find(parents[x]);
      weight[x] = weight[x] + weight[parents[x]];
      return parents[x] = tmp;
    }
  }
  void unite(int x, int y, int w) {
    int tmpx = find(x);
    int tmpy = find(y);
    if (tmpx == tmpy)
      return;
    // cout<<"weight list"<<weight[x]<<" "<<weight[y]<<" "<<w<<endl;
    if (rank[tmpx] < rank[tmpy]) {
      weight[tmpx] = w - weight[x] + weight[y];
      parents[tmpx] = tmpy;
    } else {
      weight[tmpy] = -w - weight[y] + weight[x];
      parents[tmpy] = tmpx;
      if (rank[tmpx] == rank[tmpy])
        rank[tmpx]++;
    }
  }
  bool same(int x, int y) { return (find(x) == find(y)); }

  int get_weight(int x, int y) {
    if (find(x) == find(y)) {
      // cout<<"get weight "<<weight[x]<<" "<<weight[y]<<endl;
      return weight[x] - weight[y];
    } else {
      return -2000000;
    }
  }
};
int main() {
  char c;
  int a, b, w;
  int n, m;
  while (cin >> n >> m, n != 0 || m != 0) {
    union_find uf(n + 1);
    for (int i = 0; i < m; i++) {
      cin >> c;
      if (c == '!') {
        cin >> a >> b >> w;
        uf.unite(a, b, w);
      } else if (c == '?') {
        cin >> a >> b;
        if (uf.same(a, b)) {
          int tmp = uf.get_weight(a, b);
          if (tmp != -2000000) {
            cout << tmp << endl;
          } else {
            return 0;
          }
        } else {
          cout << "UNKNOWN" << endl;
        }
      } else {
        cout << "???" << endl;
      }
    }
  }
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cstdio>
#include <iostream>
using namespace std;
#define MAX_N 100100

class union_find {
private:
  int parents[MAX_N];
  int rank[MAX_N];
  int weight[MAX_N];

public:
  union_find() {
    for (int i = 0; i < MAX_N; i++) {
      parents[i] = i;
      rank[i] = 0;
      weight[i] = 0;
    }
  }
  union_find(int n) {
    for (int i = 0; i < n; i++) {
      parents[i] = i;
      rank[i] = 0;
      weight[i] = 0;
    }
  }
  int find(int x) {
    if (parents[x] == x) {
      return x;
    } else {
      int tmp = find(parents[x]);
      weight[x] = weight[x] + weight[parents[x]];
      return parents[x] = tmp;
    }
  }
  void unite(int x, int y, int w) {
    int tmpx = find(x);
    int tmpy = find(y);
    if (tmpx == tmpy)
      return;
    // cout<<"weight list"<<weight[x]<<" "<<weight[y]<<" "<<w<<endl;
    if (rank[tmpx] < rank[tmpy]) {
      weight[tmpx] = w - weight[x] + weight[y];
      parents[tmpx] = tmpy;
    } else {
      weight[tmpy] = -w - weight[y] + weight[x];
      parents[tmpy] = tmpx;
      if (rank[tmpx] == rank[tmpy])
        rank[tmpx]++;
    }
  }
  bool same(int x, int y) { return (find(x) == find(y)); }

  int get_weight(int x, int y) {
    if (find(x) == find(y)) {
      // cout<<"get weight "<<weight[x]<<" "<<weight[y]<<endl;
      return weight[x] - weight[y];
    } else {
      return -2000000;
    }
  }
};
int main() {
  char c;
  int a, b, w;
  int n, m;
  while (cin >> n >> m, n != 0 || m != 0) {
    union_find uf(n + 1);
    for (int i = 0; i < m; i++) {
      cin >> c;
      if (c == '!') {
        cin >> a >> b >> w;
        uf.unite(a, b, w);
      } else if (c == '?') {
        cin >> a >> b;
        if (uf.same(a, b)) {
          int tmp = uf.get_weight(a, b);
          if (tmp != -2000000) {
            cout << tmp << endl;
          } else {
            return 0;
          }
        } else {
          cout << "UNKNOWN" << endl;
        }
      } else {
        cout << "???" << endl;
      }
    }
  }
}