Problem p03045 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
#include <set>
#include <vector>

static const int IINF = 1 << 30;
static const long long LINF = 1LL << 60;
static const long long MOD = 1.0e+9 + 7;

template <typename T> std::vector<T> vectors(std::size_t n, T val) {
  return std::vector<T>(n, val);
}

template <typename T, typename... Args>
auto vectors(std::size_t n, Args... args) {
  return std::vector<decltype(vectors<T>(args...))>(n, vectors<T>(args...));
}

template <class T> inline bool chmin(T &a, const T &b) {
  return (a > b) ? a = b, true : false;
}

template <class T> inline bool chmax(T &a, const T &b) {
  return (a < b) ? a = b, true : false;
}

template <class T> inline void chadd(T &a, const T &b) {
  a += b, a %= MOD;
  // TODO minus case
}

template <class T>
std::ostream &operator<<(std::ostream &s, const std::vector<T> &v) {
  if (v.empty())
    return s;
  s << *v.begin();
  for (auto iter = v.begin() + 1; iter != v.end(); ++iter)
    if (std::is_fundamental<T>::value)
      s << " " << *iter;
    else
      s << std::endl << *iter;
  return s;
}

struct UnionFind {
  std::vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        std::swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};

int main() {
  // Input
  int N, M;
  std::cin >> N >> M;

  std::vector<int> X(N);
  std::vector<int> Y(N);
  std::vector<int> Z(N);
  for (int i = 0; i < M; ++i)
    std::cin >> X[i] >> Y[i] >> Z[i];

  // Main
  UnionFind uf(N);
  for (int i = 0; i < M; ++i)
    uf.unionSet(X[i] - 1, Y[i] - 1);

  // Output
  std::set<int> s;
  // for (int i = 0; i < M; ++i)
  //   s.insert(uf.root(i));
  for (int j = 0; j < N; ++j)
    s.insert(uf.root(j));

  std::cout << s.size() << std::endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
#include <set>
#include <vector>

static const int IINF = 1 << 30;
static const long long LINF = 1LL << 60;
static const long long MOD = 1.0e+9 + 7;

template <typename T> std::vector<T> vectors(std::size_t n, T val) {
  return std::vector<T>(n, val);
}

template <typename T, typename... Args>
auto vectors(std::size_t n, Args... args) {
  return std::vector<decltype(vectors<T>(args...))>(n, vectors<T>(args...));
}

template <class T> inline bool chmin(T &a, const T &b) {
  return (a > b) ? a = b, true : false;
}

template <class T> inline bool chmax(T &a, const T &b) {
  return (a < b) ? a = b, true : false;
}

template <class T> inline void chadd(T &a, const T &b) {
  a += b, a %= MOD;
  // TODO minus case
}

template <class T>
std::ostream &operator<<(std::ostream &s, const std::vector<T> &v) {
  if (v.empty())
    return s;
  s << *v.begin();
  for (auto iter = v.begin() + 1; iter != v.end(); ++iter)
    if (std::is_fundamental<T>::value)
      s << " " << *iter;
    else
      s << std::endl << *iter;
  return s;
}

struct UnionFind {
  std::vector<int> data;
  UnionFind(int size) : data(size, -1) {}
  bool unionSet(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x])
        std::swap(x, y);
      data[x] += data[y];
      data[y] = x;
    }
    return x != y;
  }
  bool findSet(int x, int y) { return root(x) == root(y); }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
  int size(int x) { return -data[root(x)]; }
};

int main() {
  // Input
  int N, M;
  std::cin >> N >> M;

  std::vector<int> X(M);
  std::vector<int> Y(M);
  std::vector<int> Z(M);
  for (int i = 0; i < M; ++i)
    std::cin >> X[i] >> Y[i] >> Z[i];

  // Main
  UnionFind uf(N);
  for (int i = 0; i < M; ++i)
    uf.unionSet(X[i] - 1, Y[i] - 1);

  // Output
  std::set<int> s;
  // for (int i = 0; i < M; ++i)
  //   s.insert(uf.root(i));
  for (int j = 0; j < N; ++j)
    s.insert(uf.root(j));

  std::cout << s.size() << std::endl;

  return 0;
}