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

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n, m) (abs((n) - (m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP {
  L(const P &a, const P &b) {
    resize(2);
    at(0) = a;
    at(1) = b;
  }
  L() { resize(2); }
};

namespace std {
bool operator<(const P &a, const P &b) {
  return !EQ(a.X, b.X) ? a.X < b.X : a.Y < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
} // namespace std

double dot(P a, P b) { return (conj(a) * b).X; }
double cross(P a, P b) { return (conj(a) * b).Y; }
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // ccw
  if (cross(b, c) < -EPS)
    return -1; // cw
  if (dot(b, c) < EPS)
    return +2; // c-a-b
  if (norm(b) < norm(c))
    return -2; // a-b-c
  return 0;    // a-c-b
}

P projection(const L &l, const P &p) {
  double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  return m[0] + B / A * (m[1] - m[0]);
}

double getangle(const P &p, const P &a, const P &b) { // clockwise
  P proj = projection(L(p, a), b);
  int minus = (dot(a - p, b - p) >= 0) ? 1 : -1;
  if (ccw(p, a, b) != 1) {
    return atan2(abs(b - proj), minus * abs(p - proj));
  } else {
    return 2 * M_PI - atan2(abs(b - proj), minus * abs(p - proj));
  }
}
double getarea(const VP &p) {
  double ret = 0;
  for (int i = 0; i < (int)p.size(); i++) {
    ret += cross(p[i], p[(i + 1) % p.size()]);
  }
  return ret * 0.5;
}

int leftmostpoint(int &pidx, int &cidx, vector<int> &vec, VP &plist) {
  P prev = plist[pidx];
  P curr = plist[cidx];
  int nextidx = -1;
  double minangle = INF;
  for (int i = 0; i < (int)vec.size(); i++) {
    if (vec[i] == pidx)
      continue;
    double angle = getangle(curr, prev, plist[vec[i]]);
    if (angle < minangle) {
      minangle = angle;
      nextidx = i;
    }
  }
  pidx = cidx;
  cidx = vec[nextidx];
  return nextidx;
}

vector<vector<int>> makeDualGraph(vector<vector<int>> &adj, VP &plist,
                                  int &out) {
  map<pair<int, int>, int> edgelist;
  vector<vector<int>> poly;
  vector<vector<bool>> used(adj.size());
  for (int i = 0; i < (int)adj.size(); i++) {
    used[i] = vector<bool>(adj[i].size(), false);
  }

  int numarea = 0;
  for (int i = 0; i < (int)adj.size(); i++) {
    for (int j = 0; j < (int)adj[i].size(); j++) {
      if (used[i][j])
        continue;
      used[i][j] = true;
      numarea++;
      vector<int> border;
      VP vlist;
      border.push_back(i);
      vlist.push_back(plist[i]);
      int prev = i;
      int curr = adj[i][j];
      while (curr != i) {
        border.push_back(curr);
        vlist.push_back(plist[curr]);
        int idx = leftmostpoint(prev, curr, adj[curr], plist);
        used[prev][idx] = true;
      }
      poly.push_back(border);
      if (getarea(vlist) < 0)
        out = numarea - 1;
    }
  }

  vector<vector<int>> dual(numarea);
  for (int i = 0; i < numarea; i++) {
    for (int j = 0; j < (int)poly[i].size(); j++) {
      int a = poly[i][j];
      int b = poly[i][(j + 1) % (int)poly[i].size()];
      pair<int, int> key = make_pair(min(a, b), max(a, b));
      if (edgelist.count(key) == 0) {
        edgelist[key] = i;
      } else {
        dual[i].push_back(edgelist[key]);
        dual[edgelist[key]].push_back(i);
      }
    }
  }

  for (int i = 0; i < (int)dual.size(); i++) {
    sort(dual[i].begin(), dual[i].end());
    dual[i].erase(unique(dual[i].begin(), dual[i].end()), dual[i].end());
  }
  return dual;
}

int main() {
  while (1) {
    int c, w;
    cin >> c >> w;
    if (c == 0)
      break;

    VP bar(c);
    for (int i = 0; i < c; i++) {
      int x, y;
      cin >> x >> y;
      bar[i] = P(x, y);
    }

    vector<vector<int>> adj(c);
    for (int i = 0; i < w; i++) {
      int s, t;
      cin >> s >> t;
      s--;
      t--;
      adj[s].push_back(t);
      adj[t].push_back(s);
    }
    int out;
    vector<vector<int>> dual = makeDualGraph(adj, bar, out);

    int numarea = dual.size();
    set<int> reach;
    reach.insert(out);
    int ans = 0;
    while (1) {
      if ((int)reach.size() == numarea)
        break;
      set<int> newreach;
      for (set<int>::iterator itr = reach.begin(); itr != reach.end(); itr++) {
        newreach.insert(*itr);
        for (int i = 0; i < (int)dual[*itr].size(); i++) {
          newreach.insert(dual[*itr][i]);
        }
      }
      reach = newreach;
      ans++;
    }
    cout << ans << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n, m) (abs((n) - (m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP {
  L(const P &a, const P &b) {
    resize(2);
    at(0) = a;
    at(1) = b;
  }
  L() { resize(2); }
};

namespace std {
bool operator<(const P &a, const P &b) {
  return !EQ(a.X, b.X) ? a.X < b.X : a.Y < b.Y;
}
bool operator==(const P &a, const P &b) { return abs(a - b) < EPS; }
} // namespace std

double dot(P a, P b) { return (conj(a) * b).X; }
double cross(P a, P b) { return (conj(a) * b).Y; }
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return +1; // ccw
  if (cross(b, c) < -EPS)
    return -1; // cw
  if (dot(b, c) < EPS)
    return +2; // c-a-b
  if (norm(b) < norm(c))
    return -2; // a-b-c
  return 0;    // a-c-b
}

P projection(const L &l, const P &p) {
  double t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  return m[0] + B / A * (m[1] - m[0]);
}

double getangle(const P &p, const P &a, const P &b) { // clockwise
  P proj = projection(L(p, a), b);
  int minus = (dot(a - p, b - p) >= 0) ? 1 : -1;
  if (ccw(p, a, b) != 1) {
    return atan2(abs(b - proj), minus * abs(p - proj));
  } else {
    return 2 * M_PI - atan2(abs(b - proj), minus * abs(p - proj));
  }
}

void trace(int cidx, vector<vector<int>> &adj, map<pair<int, int>, int> &rest,
           VP &plist, vector<int> &poly, bool outside) {
  P curr = plist[cidx];
  P prev = P(0, -1);
  int pidx = -1;
  poly = vector<int>();
  bool first = true;
  while (1) {
    int next = -1;
    bool rightmost = !first && !outside;
    double m_angle = rightmost ? -INF : INF;
    for (int i = 0; i < (int)adj[cidx].size(); i++) {
      if (adj[cidx][i] == pidx)
        continue;
      int imin = min(cidx, adj[cidx][i]);
      int imax = max(cidx, adj[cidx][i]);
      if (rest[make_pair(imin, imax)] == 0)
        continue;
      double angle = getangle(curr, prev, plist[adj[cidx][i]]);
      if ((rightmost && angle > m_angle) || (!rightmost && angle < m_angle)) {
        next = adj[cidx][i];
        m_angle = angle;
      }
    }
    if (!first)
      rest[make_pair(min(cidx, next), max(cidx, next))]--;
    if (!first && next == poly[0])
      break;
    if (next == -1)
      exit(1);
    poly.push_back(next);
    prev = curr;
    pidx = cidx;
    curr = plist[next];
    cidx = next;
    first = false;
  }
}

void makeDualGraph(vector<vector<int>> &adj, vector<vector<int>> &dual,
                   VP &plist) {
  int n = adj.size();
  vector<int> degree(n);
  map<pair<int, int>, int> rest;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < (int)adj[i].size(); j++) {
      if (i < adj[i][j]) {
        rest[make_pair(i, adj[i][j])] = 2;
      }
    }
    degree[i] = adj[i].size() * 2;
  }

  map<pair<int, int>, int> edgelist;
  dual = vector<vector<int>>();
  dual.reserve(200);

  int sptr = 0;
  int areaidx = -1;
  bool first = true;
  while (1) {
    while (sptr < n && degree[sptr] == 0)
      sptr++;
    if (sptr == n)
      break;
    areaidx++;

    vector<int> border;
    trace(sptr, adj, rest, plist, border, first);
    dual.push_back(vector<int>());

    for (int i = 0; i < (int)border.size(); i++) {
      int a = border[i];
      int b = border[(i + 1) % (int)border.size()];
      if (a > b)
        swap(a, b);
      degree[a]--;
      degree[b]--;
      if (edgelist.count(make_pair(a, b)) == 0) {
        edgelist[make_pair(a, b)] = areaidx;
      } else {
        dual[areaidx].push_back(edgelist[make_pair(a, b)]);
        dual[edgelist[make_pair(a, b)]].push_back(areaidx);
      }
    }
    first = false;
  }

  for (int i = 0; i <= areaidx; i++) {
    sort(dual[i].begin(), dual[i].end());
    dual[i].erase(unique(dual[i].begin(), dual[i].end()), dual[i].end());
  }
}

int main() {
  while (1) {
    int c, w;
    cin >> c >> w;
    if (c == 0)
      break;

    vector<pair<P, int>> bar(c);
    for (int i = 0; i < c; i++) {
      int x, y;
      cin >> x >> y;
      bar[i] = make_pair(P(x, y), i + 1);
    }
    sort(bar.begin(), bar.end());

    vector<int> backref(c + 1);
    VP p(c);
    for (int i = 0; i < c; i++) {
      backref[bar[i].second] = i;
      p[i] = bar[i].first;
    }

    vector<vector<int>> adj(c), dual;
    for (int i = 0; i < w; i++) {
      int s, t;
      cin >> s >> t;
      adj[backref[s]].push_back(backref[t]);
      adj[backref[t]].push_back(backref[s]);
    }
    makeDualGraph(adj, dual, p);

    int numarea = dual.size();
    set<int> reach;
    reach.insert(0);
    int ans = 0;
    while (1) {
      if ((int)reach.size() == numarea)
        break;
      set<int> newreach;
      for (set<int>::iterator itr = reach.begin(); itr != reach.end(); itr++) {
        newreach.insert(*itr);
        for (int i = 0; i < (int)dual[*itr].size(); i++) {
          newreach.insert(dual[*itr][i]);
        }
      }
      reach = newreach;
      ans++;
    }
    cout << ans << endl;
  }
  return 0;
}