Problem p00909 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm> // other
#include <bitset>
#include <cassert> // c
#include <complex>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream> // io
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <vector> // container

using namespace std;
typedef long long ll;

#define ALL(c) (c).begin(), (c).end()
#define FOR(i, l, r) for (int i = (int)l; i < (int)r; ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORr(i, l, r) for (int i = (int)r - 1; i >= (int)l; --i)
#define REPr(i, n) FORr(i, 0, n)
#define EACH(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define IN(l, v, r) ((l) <= (v) && (v) < (r))
#define UNIQUE(v) v.erase(unique(ALL(v)), v.end())
// debug
#define DUMP(x) cerr << #x << " = " << (x)
#define LINE() cerr << " (L" << __LINE__ << ")"

template <typename T, typename U> T pmod(T x, U M) { return (x % M + M) % M; }

// verified by AOJ0118
struct UnionFind {
  vector<int> par, rank, ss;
  int size;
  vector<int> ws;
  UnionFind(int n) {
    REP(i, n) par.push_back(i);
    rank = vector<int>(n);
    ss = vector<int>(n, 1);
    size = n;

    ws = vector<int>(n);
  }
  int root(int x) {
    if (par[x] == x)
      return x;
    int r = root(par[x]);
    ws[x] += ws[par[x]];
    return par[x] = r;
  }
  int val(int x) {
    root(x);
    return ws[x];
  }
  bool same(int x, int y) { return root(x) == root(y); }
  void unite(int x, int y, int w = 0) {
    int vx = val(x), vy = val(y);
    x = root(x);
    y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y]) { // root y
      ws[x] = w + vy - vx;
      par[x] = y;
      ss[y] += ss[x];
    } else { // root x
      ws[y] = -w + vx - vy;
      par[y] = x;
      ss[x] += ss[y];
    }
    if (rank[x] == rank[y])
      rank[x]++;
    size--;
  }
  int getS(int x) { return ss[root(x)]; }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cerr << fixed << setprecision(20);
  cout << fixed << setprecision(20);
  while (true) {
    int N, M;
    cin >> N >> M;
    if (N == 0)
      break;
    UnionFind uf(N);
    REP(i, M) {
      char c;
      int a, b, w;
      cin >> c >> a >> b;
      a--;
      b--;

      // REP(i,N)cerr <<uf.par[i] <<" ";cerr <<endl;
      // 		REP(i,N)cerr <<uf.val(i) <<" ";cerr <<endl;
      if (c == '!') {
        cin >> w;
        uf.unite(a, b, w);
      } else {
        if (!uf.same(a, b)) {
          cout << "UNKNOWN" << endl;
        } else {
          cout << uf.val(a) - uf.val(b) << endl;
        }
      }
      // cerr <<"aaa"<<endl;
    }
  }
}

Error: 0
0 1 
0 0 
0 0 
0 -1 
0 1 
0 0 
0 0 
0 -1 
0 1 2 3 
0 0 0 0 
0 0 2 3 
0 -100 0 0 
0 0 2 3 
0 -100 0 0 
0 0 0 3 
0 -100 -200 0 
0 0 0 3 
0 -100 -200 0 
0 0 0 3 
0 -100 -200 0 
0 0 0 0 
0 -100 -200 -50 


Fixed submission:

#include <algorithm> // other
#include <bitset>
#include <cassert> // c
#include <complex>
#include <ctime>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream> // io
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <vector> // container

using namespace std;
typedef long long ll;

#define ALL(c) (c).begin(), (c).end()
#define FOR(i, l, r) for (int i = (int)l; i < (int)r; ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORr(i, l, r) for (int i = (int)r - 1; i >= (int)l; --i)
#define REPr(i, n) FORr(i, 0, n)
#define EACH(i, c)                                                             \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define IN(l, v, r) ((l) <= (v) && (v) < (r))
#define UNIQUE(v) v.erase(unique(ALL(v)), v.end())
// debug
#define DUMP(x) cerr << #x << " = " << (x)
#define LINE() cerr << " (L" << __LINE__ << ")"

template <typename T, typename U> T pmod(T x, U M) { return (x % M + M) % M; }

// verified by AOJ0118
struct UnionFind {
  vector<int> par, rank, ss;
  int size;
  vector<int> ws;
  UnionFind(int n) {
    REP(i, n) par.push_back(i);
    rank = vector<int>(n);
    ss = vector<int>(n, 1);
    size = n;

    ws = vector<int>(n);
  }
  int root(int x) {
    if (par[x] == x)
      return x;
    int r = root(par[x]);
    ws[x] += ws[par[x]];
    return par[x] = r;
  }
  int val(int x) {
    root(x);
    return ws[x];
  }
  bool same(int x, int y) { return root(x) == root(y); }
  void unite(int x, int y, int w = 0) {
    int vx = val(x), vy = val(y);
    x = root(x);
    y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y]) { // root y
      ws[x] += w + vy;
      par[x] = y;
      ss[y] += ss[x];
    } else { // root x
      ws[y] += -w + vx;
      par[y] = x;
      ss[x] += ss[y];
    }
    if (rank[x] == rank[y])
      rank[x]++;
    size--;
  }
  int getS(int x) { return ss[root(x)]; }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cerr << fixed << setprecision(20);
  cout << fixed << setprecision(20);
  while (true) {
    int N, M;
    cin >> N >> M;
    if (N == 0)
      break;
    UnionFind uf(N);
    REP(i, M) {
      char c;
      int a, b, w;
      cin >> c >> a >> b;
      a--;
      b--;

      REP(i, N) cerr << uf.par[i] << " ";
      cerr << endl;
      REP(i, N) cerr << uf.val(i) << " ";
      cerr << endl;
      if (c == '!') {
        cin >> w;
        uf.unite(a, b, w);
      } else {
        if (!uf.same(a, b)) {
          cout << "UNKNOWN" << endl;
        } else {
          cout << uf.val(a) - uf.val(b) << endl;
        }
      }
      // cerr <<"aaa"<<endl;
    }
  }
}