Problem p02536 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define REP(i, x, n) for (int i = x; i < (int)n; i++)
#define rep(i, n) REP(i, 0, n)
#define sp(p) cout << setprecision(16) << fixed << p << endl;
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define SORT(a) sort(all(a))
#define RSORT(a) sort(rall(a))
#define UNIQ(a) unique(all(a))
#define UNIQNUM(a) UNIQ(a) - a.begin()
#define UNIQIT(a) a.erase(UNIQ(a), a.end());
#define VOUT(v, i)                                                             \
  rep(i, v.size()) cout << v[i] << (i == v.size() - 1 ? "\n" : " ");
#define vout(v) VOUT(v, z);
#define vdbg(v, i)                                                             \
  cout << #v << ": ";                                                          \
  for (int i = 0; i < (int)v.size(); i++) {                                    \
    cout << v[i] << " ";                                                       \
  }                                                                            \
  cout << "\n";
#define vmin(v) *min_element(all(v))
#define vmax(v) *max_element(all(v))
#define vsum(v) accumulate(all(v), 0LL)
#define MOUT(m, r, c)                                                          \
  rep(i, r) {                                                                  \
    rep(j, c) { cout << m[i][j] << " "; }                                      \
    cout << endl;                                                              \
  }
#define mout(m) MOUT(m, m.size(), m[0].size())
#define debg(a) cout << #a << ": " << a << endl;
#define out(a) debg(a);
#define aout(a)                                                                \
  for (auto &e : a)                                                            \
    cout << e << " ";
#define show(a)                                                                \
  for (cont & y : a) {                                                         \
    for (cont & x : y) {                                                       \
      cout << x << " ";                                                        \
    }                                                                          \
    cout << endl;                                                              \
  }
#define digit(a) to_string(a).length();
// template<class T>inline int out(const T &t){ print(t); putchar('\n'); return
// 0; } template<class T>inline T gcd(T a,T b){if(b==0)return a;
// return(gcd(b,a%b));} template<class T>inline T lcm(T a,T b){return
// a/gcd(a,b)*b;}
bool is_palindrome(string s) { return s == string(s.rbegin(), s.rend()); }
#define popcount __builtin_popcount
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<vector<ll>> VV;
// const long long MOD=1000000007;
const long long INF = 1e18;
#define EPS (1e-7)
#define PI (acos(-1))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
public:
  dsu() : _n(0) {}
  dsu(int n) : _n(n), parent_or_size(n, -1) {}

  int merge(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    int x = leader(a), y = leader(b);
    if (x == y)
      return x;
    if (-parent_or_size[x] < -parent_or_size[y])
      std::swap(x, y);
    parent_or_size[x] += parent_or_size[y];
    parent_or_size[y] = x;
    return x;
  }

  bool same(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    return leader(a) == leader(b);
  }

  int leader(int a) {
    assert(0 <= a && a < _n);
    if (parent_or_size[a] < 0)
      return a;
    return parent_or_size[a] = leader(parent_or_size[a]);
  }

  int size(int a) {
    assert(0 <= a && a < _n);
    return -parent_or_size[leader(a)];
  }

  std::vector<std::vector<int>> groups() {
    std::vector<int> leader_buf(_n), group_size(_n);
    for (int i = 0; i < _n; i++) {
      leader_buf[i] = leader(i);
      group_size[leader_buf[i]]++;
    }
    std::vector<std::vector<int>> result(_n);
    for (int i = 0; i < _n; i++) {
      result[i].reserve(group_size[i]);
    }
    for (int i = 0; i < _n; i++) {
      result[leader_buf[i]].push_back(i);
    }
    result.erase(
        std::remove_if(result.begin(), result.end(),
                       [&](const std::vector<int> &v) { return v.empty(); }),
        result.end());
    return result;
  }

private:
  int _n;
  // root node: -1 * component size
  // otherwise: parent
  std::vector<int> parent_or_size;
};

int main() {
  long long N;
  scanf("%lld", &N);
  long long M;
  scanf("%lld", &M);
  std::vector<long long> A(M);
  std::vector<long long> B(M);
  for (int i = 0; i < M; i++) {
    scanf("%lld", &A[i]);
    scanf("%lld", &B[i]);
  }
  dsu d(N);
  for (long long i = 0; i < M; i++) {
    d.merge(A[i], B[i]);
  }
  vector<vector<int>> v = d.groups();
  // out(v.size());
  cout << v.size() - 1 << endl;

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define REP(i, x, n) for (int i = x; i < (int)n; i++)
#define rep(i, n) REP(i, 0, n)
#define sp(p) cout << setprecision(16) << fixed << p << endl;
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define SORT(a) sort(all(a))
#define RSORT(a) sort(rall(a))
#define UNIQ(a) unique(all(a))
#define UNIQNUM(a) UNIQ(a) - a.begin()
#define UNIQIT(a) a.erase(UNIQ(a), a.end());
#define VOUT(v, i)                                                             \
  rep(i, v.size()) cout << v[i] << (i == v.size() - 1 ? "\n" : " ");
#define vout(v) VOUT(v, z);
#define vdbg(v, i)                                                             \
  cout << #v << ": ";                                                          \
  for (int i = 0; i < (int)v.size(); i++) {                                    \
    cout << v[i] << " ";                                                       \
  }                                                                            \
  cout << "\n";
#define vmin(v) *min_element(all(v))
#define vmax(v) *max_element(all(v))
#define vsum(v) accumulate(all(v), 0LL)
#define MOUT(m, r, c)                                                          \
  rep(i, r) {                                                                  \
    rep(j, c) { cout << m[i][j] << " "; }                                      \
    cout << endl;                                                              \
  }
#define mout(m) MOUT(m, m.size(), m[0].size())
#define debg(a) cout << #a << ": " << a << endl;
#define out(a) debg(a);
#define aout(a)                                                                \
  for (auto &e : a)                                                            \
    cout << e << " ";
#define show(a)                                                                \
  for (cont & y : a) {                                                         \
    for (cont & x : y) {                                                       \
      cout << x << " ";                                                        \
    }                                                                          \
    cout << endl;                                                              \
  }
#define digit(a) to_string(a).length();
// template<class T>inline int out(const T &t){ print(t); putchar('\n'); return
// 0; } template<class T>inline T gcd(T a,T b){if(b==0)return a;
// return(gcd(b,a%b));} template<class T>inline T lcm(T a,T b){return
// a/gcd(a,b)*b;}
bool is_palindrome(string s) { return s == string(s.rbegin(), s.rend()); }
#define popcount __builtin_popcount
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef vector<vector<ll>> VV;
// const long long MOD=1000000007;
const long long INF = 1e18;
#define EPS (1e-7)
#define PI (acos(-1))
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
public:
  dsu() : _n(0) {}
  dsu(int n) : _n(n), parent_or_size(n, -1) {}

  int merge(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    int x = leader(a), y = leader(b);
    if (x == y)
      return x;
    if (-parent_or_size[x] < -parent_or_size[y])
      std::swap(x, y);
    parent_or_size[x] += parent_or_size[y];
    parent_or_size[y] = x;
    return x;
  }

  bool same(int a, int b) {
    assert(0 <= a && a < _n);
    assert(0 <= b && b < _n);
    return leader(a) == leader(b);
  }

  int leader(int a) {
    assert(0 <= a && a < _n);
    if (parent_or_size[a] < 0)
      return a;
    return parent_or_size[a] = leader(parent_or_size[a]);
  }

  int size(int a) {
    assert(0 <= a && a < _n);
    return -parent_or_size[leader(a)];
  }

  std::vector<std::vector<int>> groups() {
    std::vector<int> leader_buf(_n), group_size(_n);
    for (int i = 0; i < _n; i++) {
      leader_buf[i] = leader(i);
      group_size[leader_buf[i]]++;
    }
    std::vector<std::vector<int>> result(_n);
    for (int i = 0; i < _n; i++) {
      result[i].reserve(group_size[i]);
    }
    for (int i = 0; i < _n; i++) {
      result[leader_buf[i]].push_back(i);
    }
    result.erase(
        std::remove_if(result.begin(), result.end(),
                       [&](const std::vector<int> &v) { return v.empty(); }),
        result.end());
    return result;
  }

private:
  int _n;
  // root node: -1 * component size
  // otherwise: parent
  std::vector<int> parent_or_size;
};

int main() {
  long long N;
  scanf("%lld", &N);
  long long M;
  scanf("%lld", &M);
  std::vector<long long> A(M);
  std::vector<long long> B(M);
  for (int i = 0; i < M; i++) {
    scanf("%lld", &A[i]);
    scanf("%lld", &B[i]);
  }
  dsu d(N);
  for (long long i = 0; i < M; i++) {
    d.merge(A[i] - 1, B[i] - 1);
  }
  vector<vector<int>> v = d.groups();
  // out(v.size());
  cout << v.size() - 1 << endl;

  return 0;
}