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

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
using namespace std;

#define EPS 1e-8

typedef double D;
typedef complex<D> P;
typedef const P &rP;
typedef vector<D> vD;
typedef pair<D, int> pdi;

const D pi = acos(-1.0);
const P iu(0.0, 1.0);

D dot(rP a, rP b) { return real(a) * real(b) + imag(a) * imag(b); }

D cross(rP a, rP b) { return real(a) * imag(b) - imag(a) * real(b); }

P intersect(rP a, rP va, rP b, rP vb) {
  P vab = b - a;
  D t = cross(vb, vab) / cross(vb, va);
  return a + t * va;
}

vD comtang(rP c1, D r1, P c2, D r2, bool out) {
  vD ret;
  c2 -= c1;
  if (norm(c2) > EPS) {
    D sgn = (out ? -1.0 : 1.0);
    D s = (r1 + sgn * r2) / abs(c2);
    if (abs(s) < 1.0 + EPS) {
      if (s > 1.0) {
        s = 1.0;
      } else if (s < -1.0) {
        s = -1.0;
      }
      D a = arg(c2), b = asin(s) - 0.5 * pi;
      ret.resize(2);
      ret[0] = a - b;
      ret[1] = a + b;
    }
  }
  return ret;
}

struct comparer {
  bool operator()(D x, D y) const { return x < y - EPS; }
};

struct arcinfo {
  P cen;
  D rd, af, al;
  map<D, int, comparer> mp;

  arcinfo(rP p1, rP p2, rP p3, rP p4) {
    P va = p2 - p1, vb = p4 - p3;
    if (abs(cross(va, vb)) < EPS) {
      cen = 0.5 * (p2 + p3);
    } else {
      cen = intersect(p2, va * iu, p3, vb * iu);
    }
    rd = abs(p2 - cen);

    af = arg(p2 - cen);
    al = arg(p3 - cen);
    if (cross(va, cen - p2) < 0.0) {
      swap(af, al);
    }
    af += 8.0 * pi;
    while (al < af) {
      al += 2.0 * pi;
    }
  }

  bool check(D &a) const {
    while (a < af - EPS) {
      a += 2.0 * pi;
    }
    if (a > al + EPS) {
      return false;
    }
    if (a < af) {
      a = af;
    }
    if (a > al) {
      a = al;
    }
    return true;
  }

  P point(double a) const { return cen + polar(rd, a); }
};

struct edgeinfo {
  int f, t;
  D len;
};

vector<arcinfo> arcs;
int V;

int getid(int t, D a) {
  if (!arcs[t].mp.count(a)) {
    arcs[t].mp[a] = V;
    V += 2;
  }
  return arcs[t].mp[a];
}

int main() {
  int n;
  vector<P> pts;
  double x, y;
  scanf("%d", &n);
  for (int i = 0; i < 2 * n; ++i) {
    scanf("%lf%lf", &x, &y);
    pts.push_back(P(x, y));
  }

  arcs.reserve(n);
  int k = 2 * n - 2;
  for (int i = 0; i < 2 * n; i += 2) {
    arcs.push_back(arcinfo(pts[k], pts[k + 1], pts[i], pts[i + 1]));
    k = i;
  }

  vector<edgeinfo> E;
  for (int i = 0; i < arcs.size(); ++i)
    for (int j = i + 1; j < arcs.size(); ++j) {
      vD ret = comtang(arcs[i].cen, arcs[i].rd, arcs[j].cen, arcs[j].rd, true);
      for (k = 0; k < ret.size(); ++k) {
        D a = ret[k], b = ret[k];
        if (arcs[i].check(a) && arcs[j].check(b)) {
          int ia = getid(i, a), ib = getid(j, b);
          P pa = arcs[i].point(a), pb = arcs[j].point(b);
          D ds = abs(pa - pb);

          if (cross(pa - arcs[i].cen, pb - pa) < 0.0) {
            swap(ia, ib);
          }

          E.push_back((edgeinfo){ia, ib, ds});
          E.push_back((edgeinfo){ib + 1, ia + 1, ds});
        }
      }

      ret = comtang(arcs[i].cen, arcs[i].rd, arcs[j].cen, arcs[j].rd, false);
      for (k = 0; k < ret.size(); ++k) {
        D a = ret[k], b = ret[k] + pi;
        if (arcs[i].check(a) && arcs[j].check(b)) {
          int ia = getid(i, a), ib = getid(j, b);
          P pa = arcs[i].point(a), pb = arcs[j].point(b);
          D ds = abs(pa - pb);
          if (cross(pa - arcs[i].cen, pb - pa) > 0.0) {
            E.push_back((edgeinfo){ia, ib + 1, ds});
            E.push_back((edgeinfo){ib, ia + 1, ds});
          } else {
            E.push_back((edgeinfo){ia + 1, ib, ds});
            E.push_back((edgeinfo){ib + 1, ia, ds});
          }
        }
      }
    }

  for (int i = 0; i < arcs.size(); ++i) {
    assert(!arcs[i].mp.empty());
    map<D, int, comparer>::iterator it1, it2;
    it1 = arcs[i].mp.begin();
    while (1) {
      it2 = it1;
      if (++it1 == arcs[i].mp.end()) {
        break;
      }
      int a = it1->second, b = it2->second;
      D ds = arcs[i].rd * abs(it1->first - it2->first);
      E.push_back((edgeinfo){b, a, ds});
      E.push_back((edgeinfo){a + 1, b + 1, ds});
    }
  }

  vector<vector<pdi>> G(V);
  for (int i = 0; i < E.size(); ++i) {
    G[E[i].f].push_back(pdi(E[i].len, E[i].t));
  }

  D stang = arg(pts[0] - arcs[0].cen);
  arcs[0].check(stang);
  assert(arcs[0].mp.count(stang));
  int start = arcs[0].mp[stang];

  vD dst(V, DBL_MAX);
  priority_queue<pdi, vector<pdi>, greater<pdi>> pq;
  for (int i = 0; i < G[start].size(); ++i) {
    int t = G[start][i].second;
    D d = G[start][i].first;
    dst[t] = d;
    pq.push(pdi(d, t));
  }

  while (!pq.empty()) {
    pdi p = pq.top();
    pq.pop();
    if (dst[p.second] != p.first) {
      continue;
    }
    if (p.second == start) {
      printf("%f\\n", p.first);
      return 0;
    }

    for (int i = 0; i < G[p.second].size(); ++i) {
      D d = G[p.second][i].first + p.first;
      int t = G[p.second][i].second;
      if (dst[t] > d) {
        dst[t] = d;
        pq.push(pdi(d, t));
      }
    }
  }

  fprintf(stderr, "no answer\\n");
}

Error: WA

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cfloat>
#include <cmath>
#include <complex>
#include <cstdio>
#include <functional>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <utility>
#include <vector>
using namespace std;

#define EPS 1e-8

typedef double D;
typedef complex<D> P;
typedef const P &rP;
typedef vector<D> vD;
typedef pair<D, int> pdi;

const D pi = acos(-1.0);
const P iu(0.0, 1.0);

D dot(rP a, rP b) { return real(a) * real(b) + imag(a) * imag(b); }

D cross(rP a, rP b) { return real(a) * imag(b) - imag(a) * real(b); }

P intersect(rP a, rP va, rP b, rP vb) {
  P vab = b - a;
  D t = cross(vb, vab) / cross(vb, va);
  return a + t * va;
}

vD comtang(rP c1, D r1, P c2, D r2, bool out) {
  vD ret;
  c2 -= c1;
  if (norm(c2) > EPS) {
    D sgn = (out ? -1.0 : 1.0);
    D s = (r1 + sgn * r2) / abs(c2);
    if (abs(s) < 1.0 + EPS) {
      if (s > 1.0) {
        s = 1.0;
      } else if (s < -1.0) {
        s = -1.0;
      }
      D a = arg(c2), b = asin(s) - 0.5 * pi;
      ret.resize(2);
      ret[0] = a - b;
      ret[1] = a + b;
    }
  }
  return ret;
}

struct comparer {
  bool operator()(D x, D y) const { return x < y - EPS; }
};

struct arcinfo {
  P cen;
  D rd, af, al;
  map<D, int, comparer> mp;

  arcinfo(rP p1, rP p2, rP p3, rP p4) {
    P va = p2 - p1, vb = p4 - p3;
    if (abs(cross(va, vb)) < EPS) {
      cen = 0.5 * (p2 + p3);
    } else {
      cen = intersect(p2, va * iu, p3, vb * iu);
    }
    rd = abs(p2 - cen);

    af = arg(p2 - cen);
    al = arg(p3 - cen);
    if (cross(va, cen - p2) < 0.0) {
      swap(af, al);
    }
    af += 8.0 * pi;
    while (al < af) {
      al += 2.0 * pi;
    }
  }

  bool check(D &a) const {
    while (a < af - EPS) {
      a += 2.0 * pi;
    }
    if (a > al + EPS) {
      return false;
    }
    if (a < af) {
      a = af;
    }
    if (a > al) {
      a = al;
    }
    return true;
  }

  P point(double a) const { return cen + polar(rd, a); }
};

struct edgeinfo {
  int f, t;
  D len;
};

vector<arcinfo> arcs;
int V;

int getid(int t, D a) {
  if (!arcs[t].mp.count(a)) {
    arcs[t].mp[a] = V;
    V += 2;
  }
  return arcs[t].mp[a];
}

int main() {
  int n;
  vector<P> pts;
  D x, y;
  scanf("%d", &n);
  for (int i = 0; i < 2 * n; ++i) {
    scanf("%lf%lf", &x, &y);
    pts.push_back(P(x, y));
  }

  arcs.reserve(n);
  int k = 2 * n - 2;
  for (int i = 0; i < 2 * n; i += 2) {
    arcs.push_back(arcinfo(pts[k], pts[k + 1], pts[i], pts[i + 1]));
    k = i;
  }

  vector<edgeinfo> E;
  for (int i = 0; i < arcs.size(); ++i)
    for (int j = i + 1; j < arcs.size(); ++j) {
      vD ret = comtang(arcs[i].cen, arcs[i].rd, arcs[j].cen, arcs[j].rd, true);
      for (k = 0; k < ret.size(); ++k) {
        D a = ret[k], b = ret[k];
        if (arcs[i].check(a) && arcs[j].check(b)) {
          int ia = getid(i, a), ib = getid(j, b);
          P pa = arcs[i].point(a), pb = arcs[j].point(b);
          D ds = abs(pa - pb);
          if (cross(pa - arcs[i].cen, pb - pa) < 0.0) {
            swap(ia, ib);
          }
          E.push_back((edgeinfo){ia, ib, ds});
          E.push_back((edgeinfo){ib + 1, ia + 1, ds});
        }
      }

      ret = comtang(arcs[i].cen, arcs[i].rd, arcs[j].cen, arcs[j].rd, false);
      for (k = 0; k < ret.size(); ++k) {
        D a = ret[k], b = ret[k] + pi;
        if (arcs[i].check(a) && arcs[j].check(b)) {
          int ia = getid(i, a), ib = getid(j, b);
          P pa = arcs[i].point(a), pb = arcs[j].point(b);
          D ds = abs(pa - pb);
          if (cross(pa - arcs[i].cen, pb - pa) < 0.0) {
            swap(ia, ib);
          }
          E.push_back((edgeinfo){ia, ib + 1, ds});
          E.push_back((edgeinfo){ib, ia + 1, ds});
        }
      }
    }

  for (int i = 0; i < arcs.size(); ++i) {
    assert(!arcs[i].mp.empty());
    map<D, int, comparer>::iterator it1, it2;
    it1 = arcs[i].mp.begin();
    while (1) {
      it2 = it1;
      if (++it1 == arcs[i].mp.end()) {
        break;
      }
      int a = it1->second, b = it2->second;
      D ds = arcs[i].rd * abs(it1->first - it2->first);
      E.push_back((edgeinfo){b, a, ds});
      E.push_back((edgeinfo){a + 1, b + 1, ds});
    }
  }

  vector<vector<pdi>> G(V);
  for (int i = 0; i < E.size(); ++i) {
    G[E[i].f].push_back(pdi(E[i].len, E[i].t));
  }

  D stang = arg(pts[0] - arcs[0].cen);
  arcs[0].check(stang);
  assert(arcs[0].mp.count(stang));
  int start = arcs[0].mp[stang];

  vD dst(V, DBL_MAX);
  priority_queue<pdi, vector<pdi>, greater<pdi>> pq;
  for (int i = 0; i < G[start].size(); ++i) {
    int t = G[start][i].second;
    D d = G[start][i].first;
    dst[t] = d;
    pq.push(pdi(d, t));
  }

  while (!pq.empty()) {
    pdi p = pq.top();
    pq.pop();
    if (dst[p.second] != p.first) {
      continue;
    }
    if (p.second == start) {
      printf("%f\\n", p.first);
      return 0;
    }

    for (int i = 0; i < G[p.second].size(); ++i) {
      D d = G[p.second][i].first + p.first;
      int t = G[p.second][i].second;
      if (dst[t] > d) {
        dst[t] = d;
        pq.push(pdi(d, t));
      }
    }
  }

  throw "no answer";
}