Problem p02931 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const ull mod = 1e9 + 7;
#define REP(i, n) for (int i = 0; i < (int)n; ++i)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl;

template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> v) {
  os << "(" << v.first << ", " << v.second << ")";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> v) {
  for (int i = 0; i < v.size(); i++) {
    if (i > 0) {
      os << " ";
    }
    os << v[i];
  }
  return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<vector<T>> v) {
  for (int i = 0; i < v.size(); i++) {
    if (i > 0) {
      os << endl;
    }
    os << v[i];
  }
  return os;
}

struct edge {
  ll R, C, A;
  bool operator<(const edge &right) const { return A < right.A; }
};

// par[i]  は，iがrootなら-(連結成分のサイズ)を，iがrootではないならばrootを返す
// root(x) は必ずroot を返す
struct UnionFindSize {
  vector<int> par;

  UnionFindSize(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y); // merge technique
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[root(x)]; }
};

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

  ll N, H, W;
  cin >> N >> H >> W;

  vector<edge> edges;

  REP(i, N) {
    ll R, C, A;
    cin >> R >> C >> A;
    R--, C--;
    edges.push_back(edge{R, C, A});
  }
  sort(edges.rbegin(), edges.rend());

  UnionFindSize uf(H + W);
  vector<ll> cnt(N, 0);

  ll res = 0;
  REP(i, N) {
    ll r1 = uf.root(edges[i].R);
    ll r2 = uf.root(H + edges[i].C);
    ll s1 = uf.size(r1);
    ll s2 = uf.size(r2);
    ll e1 = cnt[r1];
    ll e2 = cnt[r2];

    if (r1 == r2) {
      if (s1 > e1) {
        res += edges[i].A;
        cnt[r1]++;
      }
    } else {
      if (s1 + s2 > e1 + e2) {
        res += edges[i].A;
        uf.merge(r1, r2);
        cnt[uf.root(r1)] = e1 + e2 + 1;
      }
    }
  }

  cout << res << endl;

  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const ull mod = 1e9 + 7;
#define REP(i, n) for (int i = 0; i < (int)n; ++i)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl;

template <class S, class T>
ostream &operator<<(ostream &os, const pair<S, T> v) {
  os << "(" << v.first << ", " << v.second << ")";
  return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> v) {
  for (int i = 0; i < v.size(); i++) {
    if (i > 0) {
      os << " ";
    }
    os << v[i];
  }
  return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<vector<T>> v) {
  for (int i = 0; i < v.size(); i++) {
    if (i > 0) {
      os << endl;
    }
    os << v[i];
  }
  return os;
}

struct edge {
  ll R, C, A;
  bool operator<(const edge &right) const { return A < right.A; }
};

// par[i]  は，iがrootなら-(連結成分のサイズ)を，iがrootではないならばrootを返す
// root(x) は必ずroot を返す
struct UnionFindSize {
  vector<int> par;

  UnionFindSize(int n) : par(n, -1) {}
  void init(int n) { par.assign(n, -1); }

  int root(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = root(par[x]);
  }

  bool issame(int x, int y) { return root(x) == root(y); }

  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (par[x] > par[y])
      swap(x, y); // merge technique
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  int size(int x) { return -par[root(x)]; }
};

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

  ll N, H, W;
  cin >> N >> H >> W;

  vector<edge> edges;

  REP(i, N) {
    ll R, C, A;
    cin >> R >> C >> A;
    R--, C--;
    edges.push_back(edge{R, C, A});
  }
  sort(edges.rbegin(), edges.rend());

  UnionFindSize uf(H + W);
  vector<ll> cnt(H + W, 0);

  ll res = 0;
  REP(i, N) {
    ll r1 = uf.root(edges[i].R);
    ll r2 = uf.root(H + edges[i].C);
    ll s1 = uf.size(r1);
    ll s2 = uf.size(r2);
    ll e1 = cnt[r1];
    ll e2 = cnt[r2];

    if (r1 == r2) {
      if (s1 > e1) {
        res += edges[i].A;
        cnt[r1]++;
      }
    } else {
      if (s1 + s2 > e1 + e2) {
        res += edges[i].A;
        uf.merge(r1, r2);
        cnt[uf.root(r1)] = e1 + e2 + 1;
      }
    }
  }

  cout << res << endl;

  return 0;
}