Problem p03045 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;

constexpr int MOD = 1000000007;
constexpr int INF = 1050000000;

#define YES cout << "YES" << endl
#define NO cout << "NO" << endl
#define Yes cout << "Yes" << endl
#define No cout << "No" << endl
#define yes cout << "yes" << endl
#define no cout << "no" << endl

#define Tof(x) (x) ? Yes : No
#define TOF(x) (x) ? YES : NO
#define tof(x) (x) ? yes : no

using ll = long long;

/*vectorの要素を全部確認するやつだよ。


for (vector<int>::iterator itr = ans.begin(); itr != ans.end(); ++itr) {
        cout << *itr << " ";
}


*/

/*for文でx,yを上下左右確認するやつだよ。

int dy[] = { 0, 1, 0, -1 };
int dx[] = { 1, 0, -1, 0 };


for (int i = 0; i < 4; i++) {
        int ny = y + dy[i];
        int nx = x + dx[i];
}
*/

/*繰り返し二乗法だよ。modもとってくれるよ。n^kをmodで割った余りでやってくれるよ。

ll POW_MOD(ll n, ll k, ll mod) {
        ll r = 1;

        for (; k > 0; k >>= 1) {
                if (k & 1) {
                        r = (r * n) % mod;
                }
                n = (n * n) % mod;
        }
        return r;
}


*/

/*2重for文書くのめんどくなった時用だよ。

for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {

        }
}

*/

class UnionFind {
private:
  std::vector<int> parent;
  std::vector<int> height;
  std::vector<int> m_size;

public:
  UnionFind(int size_) : parent(size_), height(size_, 0), m_size(size_, 1) {
    for (int i = 0; i < size_; ++i)
      parent[i] = i;
  }
  void init(int size_) {
    parent.resize(size_);
    height.resize(size_, 0);
    m_size.resize(size_, 1);
    for (int i = 0; i < size_; ++i)
      parent[i] = i;
  }
  int find(int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = find(parent[x]);
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    int t = size(x) + size(y);
    m_size[x] = m_size[y] = t;
    if (height[x] < height[y])
      parent[x] = y;
    else
      parent[y] = x;
    if (height[x] == height[y])
      ++height[x];
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) {
    if (parent[x] == x)
      return m_size[x];
    return size(parent[x] = find(parent[x]));
  }
};

int main(void) {
  int n, m;
  cin >> n >> m;
  int x, y, z;

  UnionFind uf(n);
  uf.init(n);
  int ans = n;

  for (int i = 0; i < m; i++) {
    cin >> x >> y >> z;

    if (uf.same(x, y)) {
    } else {
      uf.unite(x, y);
      ans--;
    }
  }

  cout << ans << endl;
}


Fixed submission:
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;

constexpr int MOD = 1000000007;
constexpr int INF = 1050000000;

#define YES cout << "YES" << endl
#define NO cout << "NO" << endl
#define Yes cout << "Yes" << endl
#define No cout << "No" << endl
#define yes cout << "yes" << endl
#define no cout << "no" << endl

#define Tof(x) (x) ? Yes : No
#define TOF(x) (x) ? YES : NO
#define tof(x) (x) ? yes : no

using ll = long long;

/*vectorの要素を全部確認するやつだよ。


for (vector<int>::iterator itr = ans.begin(); itr != ans.end(); ++itr) {
        cout << *itr << " ";
}


*/

/*for文でx,yを上下左右確認するやつだよ。

int dy[] = { 0, 1, 0, -1 };
int dx[] = { 1, 0, -1, 0 };


for (int i = 0; i < 4; i++) {
        int ny = y + dy[i];
        int nx = x + dx[i];
}
*/

/*繰り返し二乗法だよ。modもとってくれるよ。n^kをmodで割った余りでやってくれるよ。

ll POW_MOD(ll n, ll k, ll mod) {
        ll r = 1;

        for (; k > 0; k >>= 1) {
                if (k & 1) {
                        r = (r * n) % mod;
                }
                n = (n * n) % mod;
        }
        return r;
}


*/

/*2重for文書くのめんどくなった時用だよ。

for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {

        }
}

*/

class UnionFind {
private:
  std::vector<int> parent;
  std::vector<int> height;
  std::vector<int> m_size;

public:
  UnionFind(int size_) : parent(size_), height(size_, 0), m_size(size_, 1) {
    for (int i = 0; i < size_; ++i)
      parent[i] = i;
  }
  void init(int size_) {
    parent.resize(size_);
    height.resize(size_, 0);
    m_size.resize(size_, 1);
    for (int i = 0; i < size_; ++i)
      parent[i] = i;
  }
  int find(int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = find(parent[x]);
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y)
      return;
    int t = size(x) + size(y);
    m_size[x] = m_size[y] = t;
    if (height[x] < height[y])
      parent[x] = y;
    else
      parent[y] = x;
    if (height[x] == height[y])
      ++height[x];
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) {
    if (parent[x] == x)
      return m_size[x];
    return size(parent[x] = find(parent[x]));
  }
};

int main(void) {
  int n, m;
  cin >> n >> m;
  int x, y, z;

  UnionFind uf(n + 1);
  uf.init(n + 1);
  int ans = n;

  for (int i = 0; i < m; i++) {
    cin >> x >> y >> z;

    if (uf.same(x, y)) {
    } else {
      uf.unite(x, y);
      ans--;
    }
  }

  cout << ans << endl;
}