Problem p03045 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

typedef long long ll;

#define INF 10e17
#define rep(i, n) for (long long i = 0; i < n; i++)
#define repr(i, n, m) for (long long i = m; i < n; i++)
#define END cout << endl
#define MOD 1000000007
#define pb push_back
#define sorti(x) sort(x.begin(), x.end())
#define sortd(x) sort(x.begin(), x.end(), std::greater<long long>())
#define debug(x) std::cerr << (x) << std::endl;
#define roll(x)                                                                \
  for (auto &&itr : x) {                                                       \
    debug(itr);                                                                \
  }

template <class T> inline void chmax(T &ans, T t) {
  if (t > ans)
    ans = t;
}
template <class T> inline void chmin(T &ans, T t) {
  if (t < ans)
    ans = t;
}

/* Union-Find-Tree */
/* 必ず要素数をコンストラクタに入れること */
template <class T = long long> class Union_Find {
  using size_type = std::size_t;
  using _Tp = T;

public:
  vector<_Tp> par;
  vector<_Tp> rnk;

  // 親の根を返す。値の変更は認めない。
  const _Tp &operator[](size_type child) {
    find(child);
    return par[child];
  }

  Union_Find(size_type n) {
    par.resize(n), rnk.resize(n);
    for (int i = 0; i < n; ++i) {
      par[i] = i;
      rnk[i] = 0;
    }
  }

  // 木の根を求める
  _Tp find(_Tp x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }

  // xとyの属する集合を併合
  void merge(_Tp x, _Tp y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;

    if (rnk[x] < rnk[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rnk[x] == rnk[y])
        rnk[x]++;
    }
  }

  // xとyが同じ集合に属するか否か
  bool same(_Tp x, _Tp y) { return find(x) == find(y); }
};

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

  int n, m;
  cin >> n >> m;

  vector<int> a(n), b(n), c(n);
  Union_Find<ll> uf(n);
  map<int, bool> mp;

  rep(i, m) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--, b[i]--;
    uf.merge(a[i], b[i]);
  }

  rep(i, n) {
    auto t = uf.find(i);
    mp[t] += 1;
  }

  cout << mp.size() << endl;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

typedef long long ll;

#define INF 10e17
#define rep(i, n) for (long long i = 0; i < n; i++)
#define repr(i, n, m) for (long long i = m; i < n; i++)
#define END cout << endl
#define MOD 1000000007
#define pb push_back
#define sorti(x) sort(x.begin(), x.end())
#define sortd(x) sort(x.begin(), x.end(), std::greater<long long>())
#define debug(x) std::cerr << (x) << std::endl;
#define roll(x)                                                                \
  for (auto &&itr : x) {                                                       \
    debug(itr);                                                                \
  }

template <class T> inline void chmax(T &ans, T t) {
  if (t > ans)
    ans = t;
}
template <class T> inline void chmin(T &ans, T t) {
  if (t < ans)
    ans = t;
}

/* Union-Find-Tree */
/* 必ず要素数をコンストラクタに入れること */
template <class T = long long> class Union_Find {
  using size_type = std::size_t;
  using _Tp = T;

public:
  vector<_Tp> par;
  vector<_Tp> rnk;

  // 親の根を返す。値の変更は認めない。
  const _Tp &operator[](size_type child) {
    find(child);
    return par[child];
  }

  Union_Find(size_type n) {
    par.resize(n), rnk.resize(n);
    for (int i = 0; i < n; ++i) {
      par[i] = i;
      rnk[i] = 0;
    }
  }

  // 木の根を求める
  _Tp find(_Tp x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }

  // xとyの属する集合を併合
  void merge(_Tp x, _Tp y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;

    if (rnk[x] < rnk[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rnk[x] == rnk[y])
        rnk[x]++;
    }
  }

  // xとyが同じ集合に属するか否か
  bool same(_Tp x, _Tp y) { return find(x) == find(y); }
};

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

  int n, m;
  cin >> n >> m;

  vector<int> a(m), b(m), c(m);
  Union_Find<ll> uf(n);
  map<int, bool> mp;

  rep(i, m) {
    cin >> a[i] >> b[i] >> c[i];
    a[i]--, b[i]--;
    uf.merge(a[i], b[i]);
  }

  rep(i, n) {
    auto t = uf.find(i);
    mp[t] += 1;
  }

  cout << mp.size() << endl;
}