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

#include <bits/stdc++.h>
using namespace std;

typedef complex<double> P; // Point
typedef pair<double, double> PA;
const double EPS = 1e-10;
const double PI = 6.0 * asin(0.5);

namespace std {
bool operator<(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS ? imag(a) < imag(b) : real(a) < real(b);
}
bool operator==(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS && fabs(imag(a) - imag(b)) < EPS;
}
} // namespace std
double dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }
double cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }

//  a -> b -> c テ」ツ?ォテゥツ?イテ」ツつ?ヲツ卍づ」ツ??」ツ?ョ b -> c
//  テ」ツ?ョテ・ツ青妥」ツ??
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // テ・ツ渉催ヲツ卍づィツィツ暗・ツ崢榲」ツつ?
  if (cross(b, c) < -EPS)
    return -1; // テヲツ卍づィツィツ暗・ツ崢榲」ツつ?
  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 テ」ツ?ョテ、ツクツ?ァツ崢エテァツキツ?
}

// テ・ツ??
struct Circle {
  P c;      // テ、ツクツュテ・ツソツεァツつケ
  double r; // テ・ツ債甘・ツセツ?
  Circle(P c = P(0, 0), double r = 0) : c(c), r(r) {}
};

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテ、ツコツ、テァツつケ
vector<P> getIntersectCC(Circle c1, Circle c2) {
  vector<P> res;
  double r1 = c1.r, r2 = c2.r, d;
  P p1 = c1.c, p2 = c2.c;
  d = abs(p1 - p2);

  if (d < EPS && abs(r1 - r2) < EPS)
    return res; // テ・ツ??ッツシツ妥」ツ?ィテ・ツ??ッツシツ津」ツ?古・ツ青古」ツ?佚・ツ?エテ・ツ青暗ッツシツ暗ァツ?。テゥツ卍静・ツ?凝」ツ?ォテ」ツ?ェテ」ツつ凝」ツ?淌」ツつ?ゥツ卍、テ・ツ、ツ姪ッツシツ?
  if (r1 + r2 < d - EPS || d + EPS < abs(r1 - r2))
    return res; // テ、ツコツ、テ」ツつ湘」ツつ嘉」ツ?ェテ」ツ??

  double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
  double h = sqrt(max(r1 * r1 - a * a, 0.0));
  P tmp1 = p1 + a / d * (p2 - p1);
  P tmp2 = h / d * (p2 - p1);

  if (abs(tmp2) < EPS)
    res.push_back(tmp1);
  else {
    res.push_back(P(real(tmp1) - imag(tmp2), imag(tmp1) + real(tmp2)));
    res.push_back(P(real(tmp1) + imag(tmp2), imag(tmp1) - real(tmp2)));
  }
  return res;
}

int N;

Circle C[111];
vector<PA> F[111];

bool insert_circleframe(int id, double a, double b) {
  if (a < b)
    F[id].push_back(PA(a, b));
  else {
    F[id].push_back(PA(a, 2.0 * M_PI));
    F[id].push_back(PA(0.0, b));
  }
  return true;
}

double cha(double a) {
  if (a < 0.0)
    return 2.0 * M_PI + a;
  return a;
}

double get(int id) {
  double ret = C[id].r * 2.0 * M_PI;
  // cout << C[id].c << " "<< C[id].r << " " << ret << endl;
  if (F[id].empty())
    return ret;
  sort(F[id].begin(), F[id].end());
  PA pa = F[id][0];
  for (int i = 0; i < (int)F[id].size(); i++) {
    // cout << F[id][i].first / M_PI * 180.0 << " "<< F[id][i].second / M_PI *
    // 180.0 << endl;
    if (F[id][i].first <= pa.second) {
      pa.first = min(pa.first, F[id][i].first);
      pa.second = max(pa.second, F[id][i].second);
    } else {
      ret -= (pa.second - pa.first) * C[id].r;
      pa = F[id][i];
    }
  }
  ret -= (pa.second - pa.first) * C[id].r;
  return ret;
}

bool unuse[111];
int main() {
  while (cin >> N && N) {
    for (int i = 0; i < N; i++)
      F[i].clear();
    memset(unuse, 0, sizeof(unuse));

    for (int i = 0; i < N; i++) {
      double x, y, r;
      cin >> x >> y >> r;
      C[i] = Circle(P(x, y), r);
      for (int j = 0; j < i; j++) {
        assert(C[i].r != C[j].r || C[i].c != C[j].c);
        // if( C[j].c == P(x,y) && C[j].r == r ) f = false;
      }
      // assert( f );
      // if( f )
    }
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i == j)
          continue;
        if (abs(C[i].c - C[j].c) + C[i].r - EPS < C[j].r)
          unuse[i] = true;
      }
    }

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i == j)
          continue;
        vector<P> cs = getIntersectCC(C[i], C[j]);
        if (cs.size() == 2) {
          P a = C[i].c, b = C[j].c;
          if (ccw(a, b, cs[0]) == 1)
            swap(cs[0], cs[1]);
          insert_circleframe(i, cha(arg(P(cs[0] - a))), cha(arg(P(cs[1] - a))));
        }
      }
    }

    double res = 0.0;
    for (int i = 0; i < N; i++) {
      if (unuse[i])
        continue;
      res += get(i);
    }
    printf("%.10f\\n", res);
  }
}

Error: WA

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

typedef complex<double> P; // Point
typedef pair<double, double> PA;
const double EPS = 1e-10;
const double PI = 6.0 * asin(0.5);

namespace std {
bool operator<(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS ? imag(a) < imag(b) : real(a) < real(b);
}
bool operator==(const P &a, const P &b) {
  return fabs(real(a) - real(b)) < EPS && fabs(imag(a) - imag(b)) < EPS;
}
} // namespace std
double dot(P a, P b) { return a.real() * b.real() + a.imag() * b.imag(); }
double cross(P a, P b) { return a.real() * b.imag() - a.imag() * b.real(); }

//  a -> b -> c テ」ツ?ォテゥツ?イテ」ツつ?ヲツ卍づ」ツ??」ツ?ョ b -> c
//  テ」ツ?ョテ・ツ青妥」ツ??
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // テ・ツ渉催ヲツ卍づィツィツ暗・ツ崢榲」ツつ?
  if (cross(b, c) < -EPS)
    return -1; // テヲツ卍づィツィツ暗・ツ崢榲」ツつ?
  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 テ」ツ?ョテ、ツクツ?ァツ崢エテァツキツ?
}

// テ・ツ??
struct Circle {
  P c;      // テ、ツクツュテ・ツソツεァツつケ
  double r; // テ・ツ債甘・ツセツ?
  Circle(P c = P(0, 0), double r = 0) : c(c), r(r) {}
};

// テ・ツ??」ツ?ィテ・ツ??」ツ?ョテ、ツコツ、テァツつケ
vector<P> getIntersectCC(Circle c1, Circle c2) {
  vector<P> res;
  double r1 = c1.r, r2 = c2.r, d;
  P p1 = c1.c, p2 = c2.c;
  d = abs(p1 - p2);

  if (d < EPS && abs(r1 - r2) < EPS)
    return res; // テ・ツ??ッツシツ妥」ツ?ィテ・ツ??ッツシツ津」ツ?古・ツ青古」ツ?佚・ツ?エテ・ツ青暗ッツシツ暗ァツ?。テゥツ卍静・ツ?凝」ツ?ォテ」ツ?ェテ」ツつ凝」ツ?淌」ツつ?ゥツ卍、テ・ツ、ツ姪ッツシツ?
  if (r1 + r2 < d - EPS || d + EPS < abs(r1 - r2))
    return res; // テ、ツコツ、テ」ツつ湘」ツつ嘉」ツ?ェテ」ツ??

  double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
  double h = sqrt(max(r1 * r1 - a * a, 0.0));
  P tmp1 = p1 + a / d * (p2 - p1);
  P tmp2 = h / d * (p2 - p1);

  if (abs(tmp2) < EPS)
    res.push_back(tmp1);
  else {
    res.push_back(P(real(tmp1) - imag(tmp2), imag(tmp1) + real(tmp2)));
    res.push_back(P(real(tmp1) + imag(tmp2), imag(tmp1) - real(tmp2)));
  }
  return res;
}

int N;

Circle C[111];
vector<PA> F[111];

bool insert_circleframe(int id, double a, double b) {
  if (a < b)
    F[id].push_back(PA(a, b));
  else {
    F[id].push_back(PA(a, 2.0 * M_PI));
    F[id].push_back(PA(0.0, b));
  }
  return true;
}

double cha(double a) {
  if (a < 0.0)
    return 2.0 * M_PI + a;
  return a;
}

double get(int id) {
  double ret = C[id].r * 2.0 * M_PI;
  // cout << C[id].c << " "<< C[id].r << " " << ret << endl;
  if (F[id].empty())
    return ret;
  sort(F[id].begin(), F[id].end());
  PA pa = F[id][0];
  for (int i = 0; i < (int)F[id].size(); i++) {
    // cout << F[id][i].first / M_PI * 180.0 << " "<< F[id][i].second / M_PI *
    // 180.0 << endl;
    if (F[id][i].first <= pa.second) {
      pa.first = min(pa.first, F[id][i].first);
      pa.second = max(pa.second, F[id][i].second);
    } else {
      ret -= (pa.second - pa.first) * C[id].r;
      pa = F[id][i];
    }
  }
  ret -= (pa.second - pa.first) * C[id].r;
  return ret;
}

int main() {
  while (cin >> N && N) {

    for (int i = 0; i < N; i++)
      F[i].clear();
    bool unuse[111];
    memset(unuse, 0, sizeof(unuse));
    for (int i = 0; i < N; i++) {
      int x, y, r;
      cin >> x >> y >> r;
      C[i] = Circle(P(x, y), r);
      for (int j = 0; j < i; j++) {
        assert(C[i].r != C[j].r || C[i].c != C[j].c);
        // if( C[j].c == P(x,y) && C[j].r == r ) f = false;
      }
      // assert( f );
      // if( f )
    }
    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i == j)
          continue;
        if (abs(C[i].c - C[j].c) + C[i].r - EPS < C[j].r)
          unuse[i] = true;
      }
    }

    for (int i = 0; i < N; i++) {
      for (int j = 0; j < N; j++) {
        if (i == j)
          continue;
        vector<P> cs = getIntersectCC(C[i], C[j]);
        if (cs.size() == 2) {
          P a = C[i].c, b = C[j].c;
          if (ccw(a, b, cs[0]) == 1)
            swap(cs[0], cs[1]);
          insert_circleframe(i, cha(arg(P(cs[0] - a))), cha(arg(P(cs[1] - a))));
        }
      }
    }

    double res = 0.0;
    for (int i = 0; i < N; i++) {
      if (unuse[i])
        continue;
      res += get(i);
    }
    printf("%.10f\\n", res);
  }
}