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

#include "bits/stdc++.h"

using namespace std;

typedef long long ll;
typedef pair<int, int> P;
const double EPS = 1e-12;
const int INF = numeric_limits<int>::max() / 2;
const int MOD = 1e9 + 7;

struct UFW {          // union-find with weight
  vector<int> par, w; // w := weight between parent
  UFW(int size) : par(size, -1), w(size, 0) {}
  bool unite(int x, int y, int d) {
    if (root(x) != root(y)) {
      w[root(y)] = d + weight(x) - weight(y);
      par[root(y)] = root(x);
    }
    return x != y;
  }
  void init(int size) {
    for (int i = 0; i < size; i++) {
      par[i] = i;
      w[i] = 0;
    }
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) {
    if (par[x] != x)
      return root(par[x]);
    return x;
  }
  int weight(int x) {
    // cout<<x<<endl;
    if (root(x) == x)
      return 0;
    return w[x] + weight(par[x]);
  }
  /*
  void print(int size){
      for(int i=0;i<size;i++) cout<<" "<<i;
      cout<<endl;
      for(int i=0;i<size;i++) cout<<" "<<par[i];
      cout<<endl;
      for(int i=0;i<size;i++) cout<<" "<<w[i];
      cout<<endl;
  }*/
};

struct WeightedUnionFind {
  vector<int> par; // 親の番号
  vector<int> ws;  // 親との重みの差

  WeightedUnionFind(int n) : par(n, -1), ws(n, 0) {}

  int find(int x) {
    if (par[x] < 0) {
      return x;
    } else {
      int parent = find(par[x]);
      ws[x] += ws[par[x]];
      return par[x] = parent;
    }
  }

  int weight(int x) {
    find(x);
    return ws[x];
  }

  bool unite(int x, int y, int w) { // x <-(w)- y (x + w = y)
    w += weight(x);
    w -= weight(y);
    x = find(x);
    y = find(y);

    if (x != y) {
      if (par[y] < par[x]) { // 多い方が根になるようにスワップする.
        int tmp = x;
        x = y;
        y = tmp;
        w = -w;
      }
      par[x] += par[y];
      par[y] = x;
      ws[y] = w;
      return true;
    } else {
      return false;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }

  void init(int size) {
    for (int i = 0; i < size; i++) {
      par[i] = -1;
      ws[i] = 0;
    }
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, m;
  string s;
  int a, b;
  ll w;
  WeightedUnionFind ufw(111111);
  while (cin >> n >> m, n) {
    ufw.init(n);
    for (int i = 0; i < m; i++) {
      cin >> s;
      if (s == "!") {
        cin >> a >> b >> w;
        a--;
        b--;
        ufw.unite(a, b, w);
      } else {
        cin >> a >> b;
        a--;
        b--;
        // uf.print(n);
        if (!ufw.same(a, b))
          cout << "UNKNOWN" << endl;
        else {
          cout << ufw.weight(b) - ufw.weight(a) << endl;
          // cout<<uf.weight(b)<<" "<<uf.weight(a)<<endl;
        }
      }
    }
  }
}


Error: TLE

Fixed submission:

#include "bits/stdc++.h"

using namespace std;

typedef long long ll;
typedef pair<int, int> P;
const double EPS = 1e-12;
const int INF = numeric_limits<int>::max() / 2;
const int MOD = 1e9 + 7;

struct UFW {          // union-find with weight
  vector<int> par, w; // w := weight between parent
  UFW(int size) : par(size, -1), w(size, 0) {}
  bool unite(int x, int y, int d) {
    if (root(x) != root(y)) {
      if (par[y] < par[x]) {
        swap(x, y);
        d *= -1;
      }
      w[root(y)] = d + weight(x) - weight(y);
      par[root(y)] = root(x);
    }
    return x != y;
  }
  void init(int size) {
    for (int i = 0; i < size; i++) {
      par[i] = -1;
      w[i] = 0;
    }
  }
  bool same(int x, int y) { return root(x) == root(y); }
  int root(int x) { return par[x] < 0 ? x : root(par[x]); }
  int weight(int x) {
    // cout<<x<<endl;
    if (root(x) == x)
      return 0;
    return w[x] + weight(par[x]);
  }
  void print(int size) {
    for (int i = 0; i < size; i++)
      cout << " " << i;
    cout << endl;
    for (int i = 0; i < size; i++)
      cout << " " << par[i];
    cout << endl;
    for (int i = 0; i < size; i++)
      cout << " " << w[i];
    cout << endl;
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int n, m;
  string s;
  int a, b;
  ll w;
  UFW uf(111111);
  while (cin >> n >> m, n) {
    uf.init(n);
    for (int i = 0; i < m; i++) {
      cin >> s;
      if (s == "!") {
        cin >> a >> b >> w;
        a--;
        b--;
        uf.unite(a, b, w);
      } else {
        cin >> a >> b;
        a--;
        b--;
        // uf.print(n);
        if (!uf.same(a, b))
          cout << "UNKNOWN" << endl;
        else {
          cout << uf.weight(b) - uf.weight(a) << endl;
          // cout<<uf.weight(b)<<" "<<uf.weight(a)<<endl;
        }
      }
    }
  }
}