Problem p03682 (C++)

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

#define REP(_i, _cnt) for (int _i = 0; _i < _cnt; _i++)
#define MP make_pair
#define PB push_back
#define FI first
#define SE second

#define MAX_N 110000

using namespace std;

class UnionFind {
public:
  void init(int n) {
    par.resize(n);
    rnk.resize(n);
    for (int i = 0; i <= n; i++) {
      par[i] = i;
      rnk[i] = 0;
    }
  }

  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }

  void unite(int x, int 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]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }

private:
  vector<int> par;
  vector<int> rnk;
};

int main() {
  vector<pair<int, int>> vx;
  vector<pair<int, int>> vy;
  int N;
  cin >> N;
  for (int i = 0; i < N; i++) {
    int x, y;
    cin >> x >> y;
    vx.PB(MP(x, i));
    vy.PB(MP(y, i));
  }
  sort(vx.begin(), vx.end());
  sort(vy.begin(), vy.end());

  vector<pair<int, pair<int, int>>> edge;
  for (int i = 0; i < N - 1; i++) {
    int v1, v2, cost;

    v1 = vx[i].SE;
    v2 = vx[i + 1].SE;
    cost = vx[i + 1].FI - vx[i].FI;
    edge.PB(MP(cost, MP(v1, v2)));

    v1 = vy[i].SE;
    v2 = vy[i + 1].SE;
    cost = vy[i + 1].FI - vy[i].FI;
    edge.PB(MP(cost, MP(v1, v2)));
  }
  sort(edge.begin(), edge.end());

  UnionFind uf;
  uf.init(N);
  int ans = 0;
  for (auto e : edge) {
    int v1 = e.SE.FI;
    int v2 = e.SE.SE;
    int cost = e.FI;
    if (!uf.same(v1, v2)) {
      ans += cost;
      uf.unite(v1, v2);
    }
  }
  cout << ans << endl;

  return 0;
}


Fixed submission:
#include <algorithm>
#include <iostream>
#include <vector>

#define REP(_i, _cnt) for (int _i = 0; _i < _cnt; _i++)
#define MP make_pair
#define PB push_back
#define FI first
#define SE second

#define MAX_N 110000

using namespace std;

class UnionFind {
public:
  void init(int n) {
    par.resize(n + 1);
    rnk.resize(n + 1);
    for (int i = 0; i <= n; i++) {
      par[i] = i;
      rnk[i] = 0;
    }
  }

  int find(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = find(par[x]);
  }

  void unite(int x, int 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]++;
    }
  }

  bool same(int x, int y) { return find(x) == find(y); }

private:
  vector<int> par;
  vector<int> rnk;
};

int main() {
  vector<pair<int, int>> vx;
  vector<pair<int, int>> vy;
  int N;
  cin >> N;
  for (int i = 0; i < N; i++) {
    int x, y;
    cin >> x >> y;
    vx.PB(MP(x, i));
    vy.PB(MP(y, i));
  }
  sort(vx.begin(), vx.end());
  sort(vy.begin(), vy.end());

  vector<pair<int, pair<int, int>>> edge;
  for (int i = 0; i < N - 1; i++) {
    int v1, v2, cost;

    v1 = vx[i].SE;
    v2 = vx[i + 1].SE;
    cost = vx[i + 1].FI - vx[i].FI;
    edge.PB(MP(cost, MP(v1, v2)));

    v1 = vy[i].SE;
    v2 = vy[i + 1].SE;
    cost = vy[i + 1].FI - vy[i].FI;
    edge.PB(MP(cost, MP(v1, v2)));
  }
  sort(edge.begin(), edge.end());

  UnionFind uf;
  uf.init(N);
  int ans = 0;
  for (auto e : edge) {
    int v1 = e.SE.FI;
    int v2 = e.SE.SE;
    int cost = e.FI;
    if (!uf.same(v1, v2)) {
      ans += cost;
      uf.unite(v1, v2);
    }
  }
  cout << ans << endl;

  return 0;
}