Problem p01498 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) begin(x), end(x)

using namespace std;
typedef int Weight;
Weight INF = 1000000000;

struct UnionFind {
  vector<int> parent;
  UnionFind(int n) : parent(n, -1) {}
  int root(int x) { return parent[x] < 0 ? x : parent[x] = root(parent[x]); }
  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (parent[y] < parent[x])
      swap(x, y);
    if (parent[x] == parent[y])
      --parent[x];
    parent[y] = x;
    return true;
  }
};

int main() {
  int n, w, h;
  cin >> n >> w >> h;
  vector<int> ix(w + 1, -1);
  vector<int> iy(h + 1, -1);
  bool edge = false;
  UnionFind uf(n);
  REP(i, n) {
    int x, y;
    cin >> x >> y;
    if (x == 1 || x == w || y == 1 || y == h)
      edge = true;
    if (ix[x] == -1) {
      ix[x] = i;
    } else {
      uf.merge(i, ix[x]);
    }
    if (iy[y] == -1) {
      iy[y] = i;
    } else {
      uf.merge(i, iy[y]);
    }
  }
  set<int> rt;
  REP(i, n) rt.insert(uf.root(i));
  if (rt.size() == 1) {
    cout << (n - 1) << endl;
  } else {
    int cnt = n - 1 + rt.size();
    cout << (cnt - (edge ? 1 : 0)) << endl;
  }
  return 0;
}

Error: WA

Fixed submission:

#include <bits/stdc++.h>
#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) begin(x), end(x)

using namespace std;
typedef int Weight;
Weight INF = 1000000000;

struct UnionFind {
  vector<int> parent;
  UnionFind(int n) : parent(n, -1) {}
  int root(int x) { return parent[x] < 0 ? x : parent[x] = root(parent[x]); }
  bool merge(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return false;
    if (parent[y] < parent[x])
      swap(x, y);
    if (parent[x] == parent[y])
      --parent[x];
    parent[y] = x;
    return true;
  }
};
typedef int Weight;
struct Edge {
  int src, dest;
  Weight weight;
  bool operator<(const Edge &rhs) const { return weight > rhs.weight; }
};

typedef vector<Edge> Edges;

// Kruskal
// N, operator <
Edges kruskal(int V, Edges &es) {
  sort(es.rbegin(), es.rend());
  UnionFind uf(V);
  Edges res;
  REP(i, es.size()) {
    Edge e = es[i];
    if (uf.root(e.src) != uf.root(e.dest)) {
      uf.merge(e.src, e.dest);
      res.push_back(e);
    }
  }
  return res;
}

int check(const Edges &ve, const vector<int> &id, int len,
          const vector<bool> &cond, int n) {
  auto tmp = ve;
  int cnt = 0;
  FOR(i, 1, len + 1) {
    if (id[i] >= 0) {
      tmp.push_back((Edge){id[i], n + cnt, cond[i]});
      if (cnt)
        tmp.push_back((Edge){n + cnt, n, 1});
      ++cnt;
    }
  }
  auto rve = kruskal(n + cnt, tmp);
  int sum = 0;
  for (auto e : rve)
    sum += e.weight;
  if ((int)rve.size() == n + cnt - 1)
    return sum;
  else
    return INF;
}

int main() {
  int n, w, h;
  cin >> n >> w >> h;
  vector<int> ix(w + 1, -1);
  vector<bool> ixx(w + 1);
  vector<bool> ixn(w + 1);
  vector<int> iy(h + 1, -1);
  vector<bool> iyx(h + 1);
  vector<bool> iyn(h + 1);
  Edges ve;
  REP(i, n) {
    int x, y;
    cin >> x >> y;
    if (ix[x] == -1) {
      ix[x] = i;
      ixx[x] = y == h;
      ixn[x] = y == 0;
    } else {
      ixx[x] = ixx[x] || y == h;
      ixn[x] = ixn[x] || y == 0;
      ve.push_back((Edge){i, ix[x], 1});
    }
    if (iy[y] == -1) {
      iy[y] = i;
      iyx[y] = x == w;
      iyn[y] = x == 0;
    } else {
      iyx[y] = iyx[y] || x == w;
      iyn[y] = iyn[y] || x == 0;
      ve.push_back((Edge){i, iy[y], 1});
    }
  }
  int res = INF;
  auto rve = kruskal(n, ve);
  int sum = 0;
  for (auto e : rve)
    sum += e.weight;
  if ((int)rve.size() == n - 1)
    res = min(res, sum);
  res = min(res, check(ve, ix, w, ixn, n));
  res = min(res, check(ve, ix, w, ixx, n));
  res = min(res, check(ve, iy, h, iyn, n));
  res = min(res, check(ve, iy, h, iyx, n));
  /*
  auto tmp = ve;
  int cnt = 0;
  FOR(x,1,w+1) {
    if (ix[x] >= 0) {
      tmp.push_back((Edge){ix[x], n+cnt, (ixn[x]>1)});
      if(cnt) tmp.push_back((Edge){n+cnt, n, 1});
      ++cnt;
    }
  }
  rve = kruskal(n+cnt,tmp);
  sum = 0;
  for (auto e:rve) sum += e.weight;
  if ((int)rve.size() == n+cnt-1) res = min(res, sum);
  tmp = ve;
  cnt = 0;
  FOR(x,1,w+1) {
    if (ix[x] >= 0) {
      tmp.push_back((Edge){ix[x], n+cnt, (ixx[x]<h)});
      if(cnt) tmp.push_back((Edge){n+cnt, n, 1});
      ++cnt;
    }
  }
  rve = kruskal(n+cnt,tmp);
  sum = 0;
  for (auto e:rve) sum += e.weight;
  if ((int)rve.size() == n+cnt-1) res = min(res, sum);
  tmp = ve;
  cnt = 0;
  FOR(y,1,h+1) {
    if (iy[y] >= 0) {
      tmp.push_back((Edge){iy[y], n+cnt, (iyn[y]>1)});
      if(cnt) tmp.push_back((Edge){n+cnt, n, 1});
      ++cnt;
    }
  }
  rve = kruskal(n+cnt, tmp);
  sum = 0;
  for (auto e:rve) sum += e.weight;
  if ((int)rve.size() == n+cnt-1) res = min(res, sum);
  tmp = ve;
  cnt = 0;
  FOR(y,1,h+1) {
    if (iy[y] >= 0) {
      tmp.push_back((Edge){iy[y], n+cnt, (iyx[y]<w)});
      if(cnt) tmp.push_back((Edge){n+cnt, n, 1});
      ++cnt;
    }
  }
  rve = kruskal(n+cnt,tmp);
  sum = 0;
  for (auto e:rve) sum += e.weight;
  if ((int)rve.size() == n+cnt-1) res = min(res, sum);
  */
  cerr << res << endl;
  return 0;
}