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

//
//  main.cpp
//  Atcoder1
//
//  Created by Hamske on 2020/09/17.
//  Copyright © 2020 Author. All rights reserved.
//

#include <algorithm>
#include <iostream>
#include <queue>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

// #define pb push_back
// #define mp make_pair
#define fi first
#define se second

typedef long long ll;

// #define rep(_i,iv,n) for(int _i=(int)(iv);_i<(int)(n);++_i)
#define rep0(_i, n) for (int _i = 0; _i < (int)(n); ++_i)
// #define REP(_i,iv,_l,n) for(int _i=(int)(iv),_l=(int)(n);_i<_l;++_i)
#define REP0(_i, _l, n) for (int _i = 0, _l = (int)(n); _i < _l; ++_i)

// #define all(x) (x).begin(),(x).end()
#define REPV(v, _itr, _end)                                                    \\
  for (auto _itr = (v).begin(), _end = (v).end(); _itr != _end; ++_itr)
#define REPVC(v, _itr, _end)                                                   \\
  for (auto _itr = (v).cbegin(), _end = (v).cend(); _itr != _end; ++_itr)

#define td typedef
// #define tds(stl,type,name) typedef stl<type > name;
#define tdv(type, name) typedef vector<type> name;

typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;

#define INF 1 << 30

td pair<int, int> pii;
td priority_queue<pii, vector<pii>, greater<pii>> pq;

int find(vi &G, int i) {
  int pi = i;
  while (pi != G[pi]) {
    pi = G[pi];
  }
  while (G[i] != pi) {
    int temp = G[i];
    G[i] = pi;
    i = temp;
  }
  return pi;
}
bool sameRoot(vi &G, int i, const int j, int *const pi, int *const pj) {
  if (i == j) {
    return true;
  }
  int pi1 = i;
  bool sameFlg = false;
  while (pi1 != G[pi1]) {
    pi1 = G[pi1];
    if (pi1 == j) {
      sameFlg = true;
      break;
    }
  }
  while (G[i] != pi1) {
    int temp = G[i];
    G[i] = pi1;
    i = temp;
  }
  if (sameFlg) {
    return true;
  }
  *pi = pi1;
  *pj = find(G, j);
  return pi1 == *pj;
}

void mergeUF(vi &G, vi &rank, const int p1, const int p2) {
  if (rank[p1] > rank[p2]) {
    G[p2] = p1;
  } else if (rank[p1] > rank[p2]) {
    G[p1] = p2;
  } else {
    G[p2] = p1;
    ++rank[p1];
  }
}

int main(int argc, const char *argv[]) {
  int N, M;
  cin >> N >> M;

  vi G(N), rank(N, 0);
  rep0(i, N) { G[i] = i; }
  int ufNum = N;

  rep0(i, M) {
    int a1, b1;
    cin >> a1 >> b1;
    --a1;
    --b1;
    int pa, pb;
    if (!sameRoot(G, a1, b1, &pa, &pb)) {
      mergeUF(G, rank, pa, pb);
      --ufNum;
    }
  }
  cout << (ufNum - 1) << endl;
  return 0;
}


Error: 0

Fixed submission:

//
//  main.cpp
//  Atcoder1
//
//  Created by Hamske on 2020/09/17.
//  Copyright © 2020 Author. All rights reserved.
//

#include <algorithm>
#include <iostream>
#include <queue>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

// #define pb push_back
// #define mp make_pair
#define fi first
#define se second

typedef long long ll;

// #define rep(_i,iv,n) for(int _i=(int)(iv);_i<(int)(n);++_i)
#define rep0(_i, n) for (int _i = 0; _i < (int)(n); ++_i)
// #define REP(_i,iv,_l,n) for(int _i=(int)(iv),_l=(int)(n);_i<_l;++_i)
#define REP0(_i, _l, n) for (int _i = 0, _l = (int)(n); _i < _l; ++_i)

// #define all(x) (x).begin(),(x).end()
#define REPV(v, _itr, _end)                                                    \\
  for (auto _itr = (v).begin(), _end = (v).end(); _itr != _end; ++_itr)
#define REPVC(v, _itr, _end)                                                   \\
  for (auto _itr = (v).cbegin(), _end = (v).cend(); _itr != _end; ++_itr)

#define td typedef
// #define tds(stl,type,name) typedef stl<type > name;
#define tdv(type, name) typedef vector<type> name;

typedef vector<bool> vb;
typedef vector<vb> vvb;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;

#define INF 1 << 30

td pair<int, int> pii;
td priority_queue<pii, vector<pii>, greater<pii>> pq;

class UnionFind {
private:
  int *const graph;
  int *const rank;
  int grpNum;

public:
  UnionFind(const int N) : graph(new int[N]), rank(new int[N]), grpNum(N) {
    rep0(i, N) {
      graph[i] = i;
      rank[i] = 0;
    }
  }
  ~UnionFind() {
    delete[] graph;
    delete[] rank;
  }
  int find(int idx) {
    if (graph[idx] == idx) {
      return idx;
    } else {
      return graph[idx] = find(idx);
    }
  }
  bool merge(int idx1, int idx2) {
    int p1 = find(idx1);
    int p2 = find(idx2);
    if (p1 == p2) {
      return true;
    }
    if (rank[p1] < rank[p2]) {
      graph[p1] = p2;
    } else if (rank[p2] < rank[p1]) {
      graph[p2] = p1;
    } else {
      graph[p1] = p2;
      ++rank[p2];
    }
    --grpNum;
    return false;
  }
  int getGrpNum() const { return grpNum; }
};

int main(int argc, const char *argv[]) {
  int N, M;
  cin >> N >> M;

  UnionFind uf(N);
  rep0(i, M) {
    int a1, b1;
    cin >> a1 >> b1;
    --a1;
    --b1;
    uf.merge(a1, b1);
  }
  cout << (uf.getGrpNum() - 1) << endl;

  return 0;
}