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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef long double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> seg, line;

const elem eps = 1e-8;
const elem pi = 2 * acos(0.0);

enum CCW {
  ccw_f = 0x01,
  ccw_r = 0x02,
  ccw_b = 0x04,
  ccw_l = 0x08,
  ccw_o = 0x10
};

struct edge {
  int src, dst;
  elem cost;
  edge(int src, int dst, elem cost) : src(src), dst(dst), cost(cost) {}
};

typedef vector<edge> edges;
typedef vector<edges> graph;

bool eq(elem a, elem b) { return abs(b - a) < eps; }
bool leq(elem a, elem b) { return eq(a, b) || a < b; }
bool ls(elem a, elem b) { return !eq(a, b) && a < b; }
elem dot(const point &a, const point &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
elem cross(const point &a, const point &b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}

int ccw(const point &a, point b, point c) {
  b -= a;
  c -= a;
  elem cr = cross(b, c);
  if (eq(cr, 0) && ls(dot(b, c), 0))
    return ccw_b;
  if (eq(cr, 0) && ls(abs(b), abs(c)))
    return ccw_f;
  return eq(cr, 0) ? ccw_o : cr > 0 ? ccw_l : ccw_r;
}

elem varg(const vec &a, const vec &b) {
  assert(abs(a) > 1e-7); // FAILED on Case 51
  assert(abs(b) > 1e-7);

  elem ret = arg(a) - arg(b);
  if (ls(ret, 0))
    ret += 2 * pi;
  if (ls(2 * pi, ret))
    ret -= 2 * pi;
  if (eq(ret, 2 * pi))
    ret = 0;
  return ret;
}

elem dist_l(const line &l, const point &x) {
  vec v = l.second - l.first;
  assert(!eq(abs(v), 0));
  return abs(cross(v, x - l.first)) / abs(v);
}

bool intersectedSS(const seg &s, const seg &t) {
  point a0 = s.first, a1 = s.second, b0 = t.first, b1 = t.second;
  int a = ccw(a0, a1, b0), b = ccw(b0, b1, a0), c = ccw(a0, a1, b1),
      d = ccw(b0, b1, a1);

  // if(eq(abs(a0-b0),0)||eq(abs(a0-b1),0)||eq(abs(a1-b0),0)||eq(abs(a1-b1),0))
  // return false;
  //  if((a|b|c|d)&ccw_o)return true;
  return (a | c) == (ccw_l | ccw_r) && (b | d) == (ccw_l | ccw_r);
}

point intersectionSS(const seg &a, const seg &b) {
  elem d1 = dist_l(b, a.first);
  elem d2 = dist_l(b, a.second);
  assert(!eq(d1 + d2, 0));
  return a.first + (d1 / (d1 + d2)) * (a.second - a.first);
}

namespace std {
bool operator<(const point &a, const point &b) {
  if (!eq(a.real(), b.real()))
    return a.real() < b.real();
  if (!eq(a.imag(), b.imag()))
    return a.imag() < b.imag();
  return false;
}
} // namespace std

struct di {
  elem d;
  int id;
  di(elem d, int id) : d(d), id(id) {}
  bool operator<(const di &t) const {
    if (!eq(d, t.d))
      return d < t.d;
    if (id != t.id)
      return id < t.id;
    return false;
  }
};

graph segmentsArrangement(const vector<seg> &ss, vector<point> &ps) {

  for (int i = 0; i < (int)ss.size(); ++i) {
    ps.push_back(ss[i].first);
    ps.push_back(ss[i].second);
    for (int j = i + 1; j < (int)ss.size(); ++j) {
      if (intersectedSS(ss[i], ss[j])) {
        ps.push_back(intersectionSS(ss[i], ss[j]));
      }
    }
  }

  for (int i = 0; i < (int)ps.size(); ++i) {
    for (int j = i + 1; j < (int)ps.size(); ++j) {
      if (abs(ps[j] - ps[i]) < 1e-6) {
        ps.erase(ps.begin() + j);
        j = i;
      }
    }
  }

  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  graph g(ps.size());
  for (int i = 0; i < (int)ss.size(); ++i) {
    vector<di> list;
    for (int j = 0; j < (int)ps.size(); ++j) {
      if (ccw(ss[i].first, ss[i].second, ps[j]) == ccw_o)
        list.push_back(di(abs(ss[i].first - ps[j]), j));
    }

    sort(list.begin(), list.end());
    for (int j = 0; j + 1 < (int)list.size(); ++j) {
      int a = list[j].id, b = list[j + 1].id;
      g[a].push_back(edge(a, b, abs(ps[a] - ps[b])));
      g[b].push_back(edge(b, a, abs(ps[b] - ps[a])));
    }
  }

  for (int i = 0; i < (int)g.size(); ++i) {
    for (int j = 0; j < (int)g[i].size(); ++j) {
      for (int k = 1 + j; k < (int)g[i].size(); ++k) {
        if (g[i][j].dst == g[i][k].dst) {
          g[i].erase(g[i].begin() + k);
          k = j;
        }
      }
    }
  }

  return g;
}

bool overlappedSegment(const seg &a, const seg &b) {
  if (ccw(a.first, a.second, b.first) == ccw_o &&
      ccw(a.first, a.second, b.second) == ccw_o)
    return true;
  if (ccw(b.first, b.second, a.first) == ccw_o &&
      ccw(b.first, b.second, a.second) == ccw_o)
    return true;
  return false;
}

void removeOverlappedSegments(vector<seg> &s) {
  for (int i = 0; i < (int)s.size(); ++i) {
    for (int j = i + 1; j < (int)s.size(); ++j) {
      if (overlappedSegment(s[i], s[j])) {
        s.erase(s.begin() + j);
        j = i;
      }
    }
  }
}

elem areaOfPolygon(const vector<point> &vp) {
  elem ret = 0;
  for (int i = 0; i < (int)vp.size(); ++i) {
    ret += cross(vp[i], vp[(i + 1) % vp.size()]);
  }
  return abs(ret / 2.);
}

vector<point> disolveArrangement(const graph &g, const vector<point> &ps) {

  int start = -1;
  double minY = 1000000;
  for (int i = 0; i < (int)ps.size(); ++i) {
    if (ls(ps[i].imag(), minY)) {
      minY = ps[i].imag();
      start = i;
    }
  }

  vector<int> path;
  vector<point> ret;

  int prev = -1;
  int cur = start;
  int org_prev = -1;
  int org_cur;

  path.push_back(cur);
  do {
    int cand = -1;
    double maxArg = -4 * pi;
    vector<di> v;

    // cout << prev << ' ' << cur << endl;
    for (int i = 0; i < (int)g[cur].size(); ++i) {
      edge e = g[cur][i];
      point pre;
      if (prev != -1) {
        pre = ps[prev];
      } else {
        pre = ps[cur] - point(0, 3);
      }
      v.push_back(di(varg(pre - ps[cur], ps[e.dst] - ps[cur]), e.dst));
    }

    for (int i = 0; i < (int)v.size(); ++i) {
      if (ls(maxArg, v[i].d)) {
        maxArg = v[i].d;
        cand = v[i].id;
      }
    }

    prev = cur;
    cur = cand;

    if (org_prev == -1) {
      org_prev = prev;
      org_cur = cur;
    } else if (cur == org_cur && prev == org_prev) {
      break;
    }

    path.push_back(cur);
  } while (true);

  for (int i = 0; i < (int)path.size(); ++i) {
    ret.push_back(ps[path[i]]);
  }

  return ret;
}

int main() {
  int N;
  while (cin >> N) {
    vector<seg> e;
    vector<point> ps;
    elem preX = 1000000;
    elem preY = 1000000;

    for (int i = 0; i < N; ++i) {
      elem X, Y;
      cin >> X >> Y;
      assert(-100000 <= X && X <= 100000);
      assert(-100000 <= Y && Y <= 100000);
      assert(!eq(preX, X) || !eq(preY, Y));
      if (i > 0) {
        e.push_back(seg(point(preX, preY), point(X, Y)));
      }
      preX = X;
      preY = Y;
    }

    removeOverlappedSegments(e);
    graph g = segmentsArrangement(e, ps);

    /*
    cout << setprecision(3) << "Arranged : " << endl;
    for(int i = 0; i < (int)g.size(); ++i){
      if(g[i].size()>0){
        cout << i << ps[g[i][0].src] << " : ";
        for(int j = 0; j < (int)g[i].size(); ++j){
          cout << g[i][j].dst << ps[g[i][j].dst] << ' ';
        }
        cout << endl;
      }
    }
    */

    vector<point> vv = disolveArrangement(g, ps);
    double S = areaOfPolygon(vv);

    cout << fixed << setprecision(12) << S << endl;
  }

  return 0;
}

Error: WA

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

typedef long double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> seg, line;

const elem eps = 1e-7;
const elem pi = 2 * acos(0.0);

enum CCW {
  ccw_f = 0x01,
  ccw_r = 0x02,
  ccw_b = 0x04,
  ccw_l = 0x08,
  ccw_o = 0x10
};

struct edge {
  int src, dst;
  elem cost;
  edge(int src, int dst, elem cost) : src(src), dst(dst), cost(cost) {}
};

typedef vector<edge> edges;
typedef vector<edges> graph;

bool eq(elem a, elem b) { return abs(b - a) < eps; }
bool leq(elem a, elem b) { return eq(a, b) || a < b; }
bool ls(elem a, elem b) { return !eq(a, b) && a < b; }
elem dot(const point &a, const point &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
elem cross(const point &a, const point &b) {
  return (a.real() * b.imag() - a.imag() * b.real());
}

int ccw(const point &a, point b, point c) {
  b -= a;
  c -= a;
  elem cr = cross(b, c);
  if (eq(cr, 0) && ls(dot(b, c), 0))
    return ccw_b;
  if (eq(cr, 0) && ls(abs(b), abs(c)))
    return ccw_f;
  return eq(cr, 0) ? ccw_o : cr > 0 ? ccw_l : ccw_r;
}

elem varg(const vec &a, const vec &b) {
  assert(abs(a) > 1e-7);
  assert(abs(b) > 1e-7);

  elem ret = arg(a) - arg(b);
  if (ls(ret, 0))
    ret += 2 * pi;
  if (ls(2 * pi, ret))
    ret -= 2 * pi;
  if (eq(ret, 2 * pi))
    ret = 0;
  return ret;
}

elem dist_l(const line &l, const point &x) {
  vec v = l.second - l.first;
  assert(!eq(abs(v), 0));
  return abs(cross(v, x - l.first)) / abs(v);
}

bool intersectedSS(const seg &s, const seg &t) {
  point a0 = s.first, a1 = s.second, b0 = t.first, b1 = t.second;
  int a = ccw(a0, a1, b0), b = ccw(b0, b1, a0), c = ccw(a0, a1, b1),
      d = ccw(b0, b1, a1);

  if (eq(abs(a0 - b0), 0) || eq(abs(a0 - b1), 0) || eq(abs(a1 - b0), 0) ||
      eq(abs(a1 - b1), 0))
    return false;

  if ((a | b | c | d) & ccw_o)
    return true;
  return (a | c) == (ccw_l | ccw_r) && (b | d) == (ccw_l | ccw_r);
}

point intersectionSS(const seg &a, const seg &b) {
  elem d1 = dist_l(b, a.first);
  elem d2 = dist_l(b, a.second);
  assert(!eq(d1 + d2, 0));
  return a.first + (d1 / (d1 + d2)) * (a.second - a.first);
}

namespace std {
bool operator<(const point &a, const point &b) {
  if (!eq(a.real(), b.real()))
    return a.real() < b.real();
  if (!eq(a.imag(), b.imag()))
    return a.imag() < b.imag();
  return false;
}
} // namespace std

struct di {
  elem d;
  int id;
  di(elem d, int id) : d(d), id(id) {}
  bool operator<(const di &t) const {
    if (!eq(d, t.d))
      return d < t.d;
    if (id != t.id)
      return id < t.id;
    return false;
  }
};

graph segmentsArrangement(const vector<seg> &ss, vector<point> &ps) {
  for (int i = 0; i < (int)ss.size(); ++i) {
    ps.push_back(ss[i].first);
    ps.push_back(ss[i].second);
    for (int j = i + 1; j < (int)ss.size(); ++j) {
      if (intersectedSS(ss[i], ss[j])) {
        ps.push_back(intersectionSS(ss[i], ss[j]));
      }
    }
  }

  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());

  graph g(ps.size());
  for (int i = 0; i < (int)ss.size(); ++i) {
    vector<di> list;
    for (int j = 0; j < (int)ps.size(); ++j) {
      if (ccw(ss[i].first, ss[i].second, ps[j]) == ccw_o)
        list.push_back(di(abs(ss[i].first - ps[j]), j));
    }

    sort(list.begin(), list.end());
    for (int j = 0; j + 1 < (int)list.size(); ++j) {
      int a = list[j].id, b = list[j + 1].id;
      g[a].push_back(edge(a, b, abs(ps[a] - ps[b])));
      g[b].push_back(edge(b, a, abs(ps[b] - ps[a])));
    }
  }

  for (int i = 0; i < (int)g.size(); ++i) {
    for (int j = 0; j < (int)g[i].size(); ++j) {
      for (int k = 1 + j; k < (int)g[i].size(); ++k) {
        if (g[i][j].dst == g[i][k].dst) {
          g[i].erase(g[i].begin() + k);
          k = j;
        }
      }
    }
  }

  return g;
}

bool overlappedSegment(const seg &a, const seg &b) {
  if (ccw(a.first, a.second, b.first) == ccw_o &&
      ccw(a.first, a.second, b.second) == ccw_o)
    return true;
  if (ccw(b.first, b.second, a.first) == ccw_o &&
      ccw(b.first, b.second, a.second) == ccw_o)
    return true;
  return false;
}

void removeOverlappedSegments(vector<seg> &s) {
  for (int i = 0; i < (int)s.size(); ++i) {
    for (int j = i + 1; j < (int)s.size(); ++j) {
      if (overlappedSegment(s[i], s[j])) {
        s.erase(s.begin() + j);
        j = i;
      }
    }
  }
}

elem areaOfPolygon(const vector<point> &vp) {
  elem ret = 0;
  for (int i = 0; i < (int)vp.size(); ++i) {
    ret += cross(vp[i], vp[(i + 1) % vp.size()]);
  }
  return abs(ret / 2.);
}

vector<point> disolveArrangement(const graph &g, const vector<point> &ps) {

  int start = -1;
  double minY = 1000000;
  for (int i = 0; i < (int)ps.size(); ++i) {
    if (ls(ps[i].imag(), minY)) {
      minY = ps[i].imag();
      start = i;
    }
  }

  vector<int> path;
  vector<point> ret;

  int prev = -1;
  int cur = start;
  int org_prev = -1;
  int org_cur;

  path.push_back(cur);
  do {
    int cand = -1;
    double maxArg = -4 * pi;
    vector<di> v;

    // cout << prev << ' ' << cur << endl;

    for (int i = 0; i < (int)g[cur].size(); ++i) {
      edge e = g[cur][i];
      point pre;
      if (prev != -1) {
        pre = ps[prev];
      } else {
        pre = ps[cur] - point(0, 3);
      }
      v.push_back(di(varg(pre - ps[cur], ps[e.dst] - ps[cur]), e.dst));
    }

    for (int i = 0; i < (int)v.size(); ++i) {
      if (ls(maxArg, v[i].d)) {
        maxArg = v[i].d;
        cand = v[i].id;
      }
    }

    prev = cur;
    cur = cand;

    // assert(prev>=0 && cur>=0);

    if (org_prev == -1) {
      org_prev = prev;
      org_cur = cur;
    } else if (cur == org_cur && prev == org_prev) {
      break;
    }

    path.push_back(cur);
  } while (true);

  for (int i = 0; i < (int)path.size(); ++i) {
    ret.push_back(ps[path[i]]);
  }

  return ret;
}

int main() {
  int N;
  while (cin >> N) {
    vector<seg> e;
    vector<point> ps;
    elem preX = 1000000;
    elem preY = 1000000;

    for (int i = 0; i < N; ++i) {
      elem X, Y;
      cin >> X >> Y;
      assert(-100000 <= X && X <= 100000);
      assert(-100000 <= Y && Y <= 100000);

      if (i > 0) {
        if (!eq(preX, X) || !eq(preY, Y)) {
          e.push_back(seg(point(preX, preY), point(X, Y)));
        }
      }
      preX = X;
      preY = Y;
    }

    removeOverlappedSegments(e);
    graph g = segmentsArrangement(e, ps);

    /*
    cout << "Arranged : " << endl;
    for(int i = 0; i < (int)g.size(); ++i){
      if(g[i].size()>0){
        cout << i << ps[g[i][0].src] << " : ";
        for(int j = 0; j < (int)g[i].size(); ++j){
          cout << g[i][j].dst << ps[g[i][j].dst] << ' ';
        }
        cout << endl;
      }
    }
    */

    vector<point> vv = disolveArrangement(g, ps);
    double S = areaOfPolygon(vv);

    cout << fixed << setprecision(12) << S << endl;
  }

  return 0;
}