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

#ifndef ___Rank_Union_Find
#define ___Rank_Union_Find

#include <vector>

// ------ Class ------ //
class UnionFind {
private:
  unsigned size_;
  std::vector<unsigned> par, rank;

public:
  UnionFind()
      : size_(0), par(std::vector<unsigned>()), rank(std::vector<unsigned>()){};
  UnionFind(unsigned size__) : size_(size__) {
    par.resize(size_);
    rank.resize(size_);
    for (unsigned i = 0; i < size_; i++)
      par[i] = i, rank[i] = 0;
  }
  unsigned size() { return size_; }
  unsigned root(unsigned x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool same(unsigned x, unsigned y) { return root(x) == root(y); }
  void unite(unsigned x, unsigned y) {
    x = root(x), y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else if (rank[x] == rank[y])
      par[y] = x, rank[x]++;
    else
      par[y] = x;
  }
  bool operator==(const UnionFind &u) { return par == u.par; }
  bool operator!=(const UnionFind &u) { return par != u.par; }
};

#endif

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
using namespace std;
int n;
string s;
int main() {
  while (cin >> n, n) {
    vector<int> r1(26), r2(26);
    UnionFind uf(26);
    for (int i = 0; i < n; i++) {
      cin >> s;
      int l = s.front() - 97, r = s.back() - 97;
      uf.unite(l, r);
      r1[l]++;
      r2[r]++;
    }
    set<int> s_;
    for (int i = 0; i < 26; i++) {
      if (r1[i] || r2[i])
        s_.insert(uf.root(i));
    }
    bool ok = true;
    for (int i = 0; i < 26; i++) {
      if (r1[i] != r2[i])
        ok = false;
    }
    cout << (ok && (s_.size() == 1) ? "OK" : "NG") << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#ifndef ___Rank_Union_Find
#define ___Rank_Union_Find

#include <vector>

// ------ Class ------ //
class UnionFind {
private:
  unsigned size_;
  std::vector<unsigned> par, rank;

public:
  UnionFind()
      : size_(0), par(std::vector<unsigned>()), rank(std::vector<unsigned>()){};
  UnionFind(unsigned size__) : size_(size__) {
    par.resize(size_);
    rank.resize(size_);
    for (unsigned i = 0; i < size_; i++)
      par[i] = i, rank[i] = 0;
  }
  unsigned size() { return size_; }
  unsigned root(unsigned x) { return par[x] == x ? x : par[x] = root(par[x]); }
  bool same(unsigned x, unsigned y) { return root(x) == root(y); }
  void unite(unsigned x, unsigned y) {
    x = root(x), y = root(y);
    if (x == y)
      return;
    if (rank[x] < rank[y])
      par[x] = y;
    else if (rank[x] == rank[y])
      par[y] = x, rank[x]++;
    else
      par[y] = x;
  }
  bool operator==(const UnionFind &u) { return par == u.par; }
  bool operator!=(const UnionFind &u) { return par != u.par; }
};

#endif

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
using namespace std;
int n;
string s;
int main() {
  while (cin >> n, n) {
    vector<vector<int>> G(26);
    for (int i = 0; i < n; i++) {
      cin >> s;
      G[s.front() - 97].push_back(s.back() - 97);
      G[s.back() - 97].push_back(s.front() - 97);
    }
    UnionFind uf(26);
    for (int i = 0; i < n; i++) {
      for (int j : G[i])
        uf.unite(i, j);
    }
    set<int> s_;
    for (int i = 0; i < 26; i++) {
      if (G[i].size())
        s_.insert(uf.root(i));
    }
    bool ok = true;
    for (int i = 0; i < 26; i++) {
      if (G[i].size() % 2 == 1)
        ok = false;
    }
    cout << (ok ? "OK" : "NG") << endl;
  }
  return 0;
}