Problem p03682 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> pii;

// 頂点は0からn-1
struct UnionFind {
  // par[i]はiの親で根のときは自分自身
  vector<int> par;

  // すべてが根として初期化
  // ここの書き方がわからない
  UnionFind(int N) : par(N) {
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
  int root(int x) {
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  // 木の併合
  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx == ry)
      return;
    par[rx] = ry; // xとyの根が同じでない時：xの根rxをyの根ryにつける
  }

  // x, yが属する木が同じか判定
  bool same(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

// 頂点数, 辺数
int V, E;

// MAX
const int MAX_V = 10005;
const int MAX_E = 100005;
const int INF = 1500000000;
// 辺 (各頂点にtoとcostのペアのリストが対応します)
struct edge {
  int u, v, cost;
};
edge es[MAX_E];
bool comp(const edge &e1, const edge &e2) { return e1.cost < e2.cost; }

// クラスカル法
int kruskal() {
  sort(es, es + E, comp);
  UnionFind tree(V);
  int res = 0;

  for (int i = 0; i < E; i++) {
    edge e = es[i];
    if (!tree.same(e.u, e.v)) {
      tree.unite(e.u, e.v);
      res += e.cost;
    }
  }

  return res;
}

int main() {
  cin >> V;
  pii x[MAX_V], y[MAX_V]; // 座標と頂点の番号のくみにする
  for (int i = 0; i < V; i++) {
    int p, q;
    cin >> p >> q;
    x[i] = make_pair(p, i);
    y[i] = make_pair(q, i);
  }
  sort(x, x + V);
  sort(y, y + V);
  for (int i = 0; i < V - 1; i++) {
    es[2 * i] =
        (edge){x[i].second, x[i + 1].second, x[i + 1].first - x[i].first};
    es[2 * i + 1] =
        (edge){y[i].second, y[i + 1].second, y[i + 1].first - y[i].first};
  }

  E = (V - 1) * 2;
  cout << kruskal() << endl;
}

Fixed submission:
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> pii;

// 頂点は0からn-1
struct UnionFind {
  // par[i]はiの親で根のときは自分自身
  vector<int> par;

  // すべてが根として初期化
  // ここの書き方がわからない
  UnionFind(int N) : par(N) {
    for (int i = 0; i < N; i++)
      par[i] = i;
  }

  // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
  int root(int x) {
    if (par[x] == x)
      return x;
    return par[x] = root(par[x]);
  }

  // 木の併合
  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx == ry)
      return;
    par[rx] = ry; // xとyの根が同じでない時：xの根rxをyの根ryにつける
  }

  // x, yが属する木が同じか判定
  bool same(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    return rx == ry;
  }
};

// 頂点数, 辺数
int V, E;

// MAX
const int MAX_V = 100005;
const int MAX_E = 200005;
const int INF = 1500000000;
// 辺 (各頂点にtoとcostのペアのリストが対応します)
struct edge {
  int u, v, cost;
};
edge es[MAX_E];
bool comp(const edge &e1, const edge &e2) { return e1.cost < e2.cost; }

// クラスカル法
int kruskal() {
  sort(es, es + E, comp);
  UnionFind tree(V);
  int res = 0;

  for (int i = 0; i < E; i++) {
    edge e = es[i];
    if (!tree.same(e.u, e.v)) {
      tree.unite(e.u, e.v);
      res += e.cost;
    }
  }

  return res;
}

int main() {
  cin >> V;
  pii x[MAX_V], y[MAX_V]; // 座標と頂点の番号のくみにする
  for (int i = 0; i < V; i++) {
    int p, q;
    cin >> p >> q;
    x[i] = make_pair(p, i);
    y[i] = make_pair(q, i);
  }
  sort(x, x + V);
  sort(y, y + V);
  for (int i = 0; i < V - 1; i++) {
    es[2 * i] =
        (edge){x[i].second, x[i + 1].second, x[i + 1].first - x[i].first};
    es[2 * i + 1] =
        (edge){y[i].second, y[i + 1].second, y[i + 1].first - y[i].first};
  }

  E = (V - 1) * 2;
  cout << kruskal() << endl;
}