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

#include <iostream>
#include <map>
#include <set>
#include <vector>

using namespace std;

typedef pair<int, int> vert;
typedef pair<vert, vert> edge;

#define make_edge(a, b) (a) < (b) ? make_pair((a), (b)) : make_pair((b), (a))
#define foreach(it, o)                                                         \\
  for (__typeof((o).begin()) it = (o).begin(); it != (o).end(); ++it)
const int MAXP = 16;
enum CCW { BACK, FRONT, OVER, LEFT, RIGHT };

int last_ccw;
map<vert, set<vert>> G;

inline int cross(const vert &a, const vert &b) {
  return a.first * b.second - a.second * b.first;
}

inline int dot(const vert &a, const vert &b) {
  return a.first * b.first + a.second * b.second;
}

inline int lenv(const vert &a) { return dot(a, a); }

inline int ccw(vert a, vert b, vert c) {
  b.first -= a.first;
  b.second -= a.second;
  c.first -= a.first;
  c.second -= a.second;

  int cr = cross(b, c);
  if (cr == 0 && dot(b, c) < 0)
    return BACK;
  if (cr == 0 && lenv(b) < lenv(c))
    return FRONT;
  if (cr == 0)
    return OVER;
  if (cr > 0)
    return LEFT;
  if (cr < 0)
    return RIGHT;
}

void check(vert cur,
           set<vert> &v, // vertex
           vert path[], int depth) {
  foreach (it, G[cur]) {
    if (v.find(*it) == v.end()) {
      v.insert(*it);
      path[depth] = *it;
      if (depth >= 2 && last_ccw == -1) {
        last_ccw = ccw(path[depth - 2], path[depth - 1], path[depth]);
      }
      check(*it, v, path, depth + 1);
    }
  }
  return;
}

int check_over(const set<edge> &E, const set<vert> &v) {
  int ret = 0;
  vector<vert> _v;
  foreach (it, v)
    _v.push_back(*it);

  for (int i = 0; i < (int)_v.size(); ++i) {
    for (int j = i + 1; j < (int)_v.size(); ++j) {
      edge e = make_edge(_v[i], _v[j]);
      if (E.find(e) != E.end()) {
        foreach (it, v) {
          if (e.first != *it && e.second != *it) {
            if (ccw(e.first, e.second, *it) == OVER)
              ++ret;
          }
        }
      }
    }
  }
  return ret;
}

int count_edge(const set<edge> &E, const set<vert> &v) {
  vector<vert> _v;
  foreach (it, v)
    _v.push_back(*it);
  int ret = 0;

  for (int i = 0; i < (int)_v.size(); ++i) {
    for (int j = i + 1; j < (int)_v.size(); ++j) {
      edge e = make_edge(_v[i], _v[j]);
      if (E.find(e) != E.end()) {
        ++ret;
      }
    }
  }
  return ret;
}

int main() {
  int n;
  while (cin >> n) {
    if (n == 0)
      break;

    int res[10] = {
        0,
    };

    G.clear();
    set<vert> V;
    set<edge> E;
    for (int i = 0; i < n; ++i) {
      int x, y, s, t;
      cin >> x >> y >> s >> t;
      vert P1(x, y);
      vert P2(s, t);
      V.insert(P1);
      V.insert(P2);
      G[P1].insert(P2);
      G[P2].insert(P1);
      E.insert(make_edge(P1, P2));
    }

    foreach (it, E) {
      foreach (itt, V) {
        if (it->first != *itt && it->second != *itt) {
          if (ccw(it->first, it->second, *itt) == OVER) {
            G[*itt].insert(it->first);
            G[*itt].insert(it->second);
            G[it->first].insert(*itt);
            G[it->second].insert(*itt);
          }
        }
      }
    }

    set<vert> vis;
    bool reset = false;
    foreach (it, G) {
      if (reset) {
        it = G.begin();
        reset = false;
      }
      if (vis.find(it->first) == vis.end()) {
        vis.insert(it->first);
        int len;
        set<vert> v;
        vert path[MAXP];

        for (int i = 0; i < MAXP; ++i)
          path[i] = make_pair(-1, -1);
        path[0] = it->first;
        v.insert(it->first);
        check(it->first, v, path, 1);
        foreach (itt, v)
          vis.insert(*itt);
        for (int i = 0; i < MAXP; ++i)
          if (path[i].first < 0) {
            len = i;
            break;
          }

        if (v.size() == 2) { // 1
          res[1]++;
        } else if (v.size() == 4) { // 0,7
          if (count_edge(E, v) == 4)
            res[0]++;
          else
            res[7]++;
        } else if (v.size() == 5) { // 4, 9
          if (count_edge(E, v) == 3)
            res[4]++;
          else
            res[9]++;
        } else if (v.size() == 6) {
          int co = check_over(E, v);
          if (co) { // 3,6,8
            if (count_edge(E, v) == 4)
              res[3]++;
            else {
              if (co == 2)
                res[8]++;
              else
                res[6]++;
            }
          } else { // 2,5
            set<vert> tv;
            path[0] = path[len - 1];
            tv.insert(path[len - 1]);
            last_ccw = -1;
            check(path[len - 1], tv, path, 1);

            if (last_ccw == RIGHT)
              res[2]++;
            else
              res[5]++;
          }
        }

        /* debug
        cout << v.size() << endl;
        for(int i = 0; i < 8; ++i){
          cout << path[i].first << ' ' << path[i].second << endl;
        }
        cout << "-"<<endl;
        */

        reset = true;
      }
    }
    // cout << "---" << endl;

    for (int i = 0; i < 10; ++i) {
      if (i)
        cout << ' ';
      cout << res[i];
    }
    cout << endl;
  }
  return 0;
}

Error: 0

Fixed submission:

#include <iostream>
#include <map>
#include <set>
#include <vector>

using namespace std;

typedef pair<int, int> vert;
typedef pair<vert, vert> edge;

#define make_edge(a, b) (a) < (b) ? make_pair((a), (b)) : make_pair((b), (a))
#define foreach(it, o)                                                         \\
  for (__typeof((o).begin()) it = (o).begin(); it != (o).end(); ++it)
const int MAXP = 8;
enum CCW { OVER, LEFT, RIGHT };

int last_ccw;
map<vert, set<vert>> G;

inline int cross(const vert &a, const vert &b) {
  return a.first * b.second - a.second * b.first;
}

inline int ccw(vert a, vert b, vert c) {
  b.first -= a.first;
  b.second -= a.second;
  c.first -= a.first;
  c.second -= a.second;

  int cr = cross(b, c);
  if (cr == 0)
    return OVER;
  if (cr > 0)
    return LEFT;
  if (cr < 0)
    return RIGHT;
}

void check(vert cur,
           set<vert> &v, // vertex
           vert path[], int depth) {
  foreach (it, G[cur]) {
    if (v.find(*it) == v.end()) {
      v.insert(*it);
      path[depth] = *it;
      if (depth >= 2 && last_ccw == -1) {
        last_ccw = ccw(path[depth - 2], path[depth - 1], path[depth]);
      }
      check(*it, v, path, depth + 1);
    }
  }
  return;
}

int check_over(const set<edge> &E, const set<vert> &v) {
  int ret = 0;
  vector<vert> _v;
  foreach (it, v)
    _v.push_back(*it);

  for (int i = 0; i < (int)_v.size(); ++i) {
    for (int j = i + 1; j < (int)_v.size(); ++j) {
      edge e = make_edge(_v[i], _v[j]);
      if (E.find(e) != E.end()) {
        foreach (it, v) {
          if (e.first != *it && e.second != *it) {
            if (ccw(e.first, e.second, *it) == OVER)
              ++ret;
          }
        }
      }
    }
  }
  return ret;
}

int count_edge(const set<edge> &E, const set<vert> &v) {
  vector<vert> _v;
  foreach (it, v)
    _v.push_back(*it);
  int ret = 0;

  for (int i = 0; i < (int)_v.size(); ++i) {
    for (int j = i + 1; j < (int)_v.size(); ++j) {
      edge e = make_edge(_v[i], _v[j]);
      if (E.find(e) != E.end()) {
        ++ret;
      }
    }
  }
  return ret;
}

int main() {
  int n;
  while (cin >> n) {
    if (n == 0)
      break;

    int res[10] = {
        0,
    };

    G.clear();
    set<vert> V;
    set<edge> E;
    for (int i = 0; i < n; ++i) {
      int x, y, s, t;
      cin >> x >> y >> s >> t;
      vert P1(x, y);
      vert P2(s, t);
      V.insert(P1);
      V.insert(P2);
      G[P1].insert(P2);
      G[P2].insert(P1);
      E.insert(make_edge(P1, P2));
    }

    foreach (it, E) {
      foreach (itt, V) {
        if (it->first != *itt && it->second != *itt) {
          if (ccw(it->first, it->second, *itt) == OVER) {
            G[*itt].insert(it->first);
            G[*itt].insert(it->second);
            G[it->first].insert(*itt);
            G[it->second].insert(*itt);
          }
        }
      }
    }

    set<vert> vis;
    bool reset = false;
    foreach (it, G) {
      if (reset) {
        it = G.begin();
        reset = false;
      }
      if (vis.find(it->first) == vis.end()) {
        vis.insert(it->first);
        int len;
        set<vert> v;
        vert path[MAXP];

        for (int i = 0; i < MAXP; ++i)
          path[i] = make_pair(-1, -1);
        path[0] = it->first;
        v.insert(it->first);
        check(it->first, v, path, 1);
        foreach (itt, v)
          vis.insert(*itt);
        for (int i = 0; i < MAXP; ++i)
          if (path[i].first < 0) {
            len = i;
            break;
          }

        if (v.size() == 2) { // 1
          res[1]++;
        } else if (v.size() == 4) { // 0,7
          if (count_edge(E, v) == 4)
            res[0]++;
          else
            res[7]++;
        } else if (v.size() == 5) { // 4, 9
          if (count_edge(E, v) == 3)
            res[4]++;
          else
            res[9]++;
        } else if (v.size() == 6) {
          int co = check_over(E, v);
          if (co) { // 3,6,8
            if (count_edge(E, v) == 4)
              res[3]++;
            else {
              if (co == 2)
                res[8]++;
              else
                res[6]++;
            }
          } else { // 2,5
            set<vert> tv;
            path[0] = path[len - 1];
            tv.insert(path[len - 1]);
            last_ccw = -1;
            check(path[len - 1], tv, path, 1);

            if (last_ccw == RIGHT)
              res[2]++;
            else
              res[5]++;
          }
        }

        /* debug
        cout << v.size() << endl;
        for(int i = 0; i < 8; ++i){
          cout << path[i].first << ' ' << path[i].second << endl;
        }
        cout << "-"<<endl;
        */

        reset = true;
      }
    }
    // cout << "---" << endl;

    for (int i = 0; i < 10; ++i) {
      if (i)
        cout << ' ';
      cout << res[i];
    }
    cout << endl;
  }
  return 0;
}