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

#include <algorithm>
#include <complex>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

typedef complex<double> point;
typedef vector<point> polygon;

struct line : public vector<point> {
  line(const point &a, const point &b) {
    push_back(a);
    push_back(b);
  }
};

const double eps = 1e-10;
double dot(const point &a, const point &b) { return (a * conj(b)).real(); }
double cross(const point &a, const point &b) { return (conj(a) * b).imag(); }
point vec(const line &l) { return (l[1] - l[0]); }
point unit(const point &v) { return (v / abs(v)); }
point curr(const polygon &g, int i) { return g[i]; }
point next(const polygon &g, int i) { return g[(i + 1) % g.size()]; }

namespace std {
bool operator<(const point &a, const point &b) {
  if (abs(a.real() - b.real()) > eps)
    return a.real() < b.real();
  if (abs(a.imag() - b.imag()) > eps)
    return a.imag() < b.imag();
  return false;
}
} // namespace std

int ccw(const point &a, const point &b, const point &c) {
  point u = b - a, v = c - a;
  if (cross(u, v) > 0)
    return +1;
  if (cross(u, v) < 0)
    return -1;
  if (dot(u, v) < 0)
    return +2; // c<a<b
  if (abs(u) < abs(v))
    return -2; // a<b<c
  return 0;
}

int ccw(const line &s, const point &p) { return ccw(s[0], s[1], p); }

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

point reflection(const line &l, const point &p) {
  return p + 2.0 * (projection(l, p) - p);
}

point crosspointLL(const line &l, const line &m) {
  double A = cross(vec(l), vec(m));
  double B = cross(vec(l), l[1] - m[0]);
  if (abs(A) < eps)
    return l[0];
  return m[0] + B / A * vec(m);
}

bool intersectSP(const line &s, const point &p) {
  return abs(s[0] - p) + abs(s[1] - p) < abs(s[1] - s[0]) + eps;
}

bool intersectSS(const line &s, const line &t) {
  return (ccw(s, t[0]) * ccw(s, t[1]) <= 0 && ccw(t, s[0]) * ccw(t, s[1]) <= 0);
}

bool containGP(const polygon &g, const point &p) {
  bool in = false;
  for (int i = 0; i < g.size(); i++) {
    point a = curr(g, i) - p;
    point b = next(g, i) - p;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in = !in;
    }
    if (cross(a, b) == 0 && dot(a, b) <= 0)
      return true;
  }
  return in;
}

bool containGS(const polygon &g, const line &l) {
  point v = unit(vec(l));
  vector<pair<double, point>> cp;

  cp.push_back(make_pair(dot(v, l[0] - l[0]), l[0]));
  cp.push_back(make_pair(dot(v, l[1] - l[0]), l[1]));
  for (int i = 0; i < g.size(); i++) {
    line edge(curr(g, i), next(g, i));
    if (intersectSS(l, edge)) {
      point c = crosspointLL(l, edge);
      cp.push_back(make_pair(dot(v, c - l[0]), c));
    }
  }
  sort(cp.begin(), cp.end());

  for (int i = 1; i < cp.size(); i++) {
    point p = (cp[i - 1].second + cp[i].second) / 2.0;
    if (!containGP(g, p))
      return false;
  }

  return true;
}

struct Node {
  point pos;
  vector<int> to;
  vector<double> cost;
};

struct Data {
  double d;
  int c, p;
  Data(double d, int c, int p) : d(d), c(c), p(p) {}
  bool operator<(const Data &x) const { return d > x.d; }
};

int main() {
  int N, M;
  while (cin >> N, N) {
    // 入力
    polygon building[100];

    for (int i = 0; i < N; i++) {
      cin >> M;
      for (int j = 0; j < M; j++) {
        int x, y;
        cin >> x >> y;
        building[i].push_back(point(x, y));
      }
    }

    int sx, sy, gx, gy;
    cin >> sx >> sy >> gx >> gy;

    int ax, ay, bx, by;
    cin >> ax >> ay >> bx >> by;

    point start(sx, sy);
    point goal(gx, gy);
    line mirror(point(ax, ay), point(bx, by));
    point mirror_start = reflection(mirror, start);
    point mirror_goal = reflection(mirror, goal);

    // 経路を含む建物の選択
    int b1 = -1, b2 = -1;
    for (int i = 0; i < N; i++) {
      if (containGP(building[i], start) && containGP(building[i], goal)) {
        b1 = i;
      }

      if (containGP(building[i], mirror_start) &&
          containGP(building[i], mirror_goal)) {
        b2 = i;
      }
    }

    if (b1 == -1 || b2 == -1) {
      cout << "impossible" << endl;
      continue;
    }

    for (int i = 0; i < building[b2].size(); i++) {
      building[b2][i] = reflection(mirror, building[b2][i]);
    }
    reverse(building[b2].begin(), building[b2].end());

    int gsize = 0;
    Node nodes[102];

    nodes[gsize++].pos = start;
    nodes[gsize++].pos = goal;
    for (int i = 0; i < building[b1].size(); i++) {
      nodes[gsize++].pos = building[b1][i];
    }
    for (int i = 0; i < building[b2].size(); i++) {
      nodes[gsize++].pos = building[b2][i];
    }

    for (int i = 0; i < gsize; i++)
      for (int j = 0; j < gsize; j++) {
        line edge(nodes[i].pos, nodes[j].pos);
        if (containGS(building[b1], edge) && containGS(building[b2], edge)) {
          double d = abs(nodes[i].pos - nodes[j].pos);
          nodes[i].to.push_back(j);
          nodes[j].to.push_back(i);
          nodes[i].cost.push_back(d);
          nodes[j].cost.push_back(d);
        }
      }

    priority_queue<Data> q;
    bool visit[102] = {false};
    int prev[102] = {0};

    bool ok = false;
    q.push(Data(0, 0, 0));
    while (!q.empty()) {
      Data t = q.top();
      q.pop();

      if (visit[t.c])
        continue;
      visit[t.c] = true;
      prev[t.c] = t.p;

      if (t.c == 1) {
        ok = true;
        printf("%.10lf\\n", t.d);
        break;
      }

      for (int i = 0; i < nodes[t.c].to.size(); i++) {
        int to = nodes[t.c].to[i];
        if (visit[to])
          continue;
        q.push(Data(t.d + nodes[t.c].cost[i], to, t.c));
      }
    }

    if (!ok) {
      cout << "impossible" << endl;
    }
  }
}

Error: WA

Fixed submission:

#include <algorithm>
#include <complex>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;

typedef complex<double> point;
typedef vector<point> polygon;

struct line : public vector<point> {
  line(const point &a, const point &b) {
    push_back(a);
    push_back(b);
  }
};

const double eps = 1e-10;
double dot(const point &a, const point &b) { return (a * conj(b)).real(); }
double cross(const point &a, const point &b) { return (conj(a) * b).imag(); }
point vec(const line &l) { return (l[1] - l[0]); }
point curr(const polygon &g, int i) { return g[i]; }
point next(const polygon &g, int i) { return g[(i + 1) % g.size()]; }

namespace std {
bool operator<(const point &a, const point &b) {
  if (abs(a.real() - b.real()) > eps)
    return a.real() < b.real();
  if (abs(a.imag() - b.imag()) > eps)
    return a.imag() < b.imag();
  return false;
}
} // namespace std

int ccw(const point &a, const point &b, const point &c) {
  point u = b - a, v = c - a;
  if (cross(u, v) > 0)
    return +1;
  if (cross(u, v) < 0)
    return -1;
  if (dot(u, v) < 0)
    return +2; // c<a<b
  if (abs(u) < abs(v))
    return -2; // a<b<c
  return 0;
}

int ccw(const line &s, const point &p) { return ccw(s[0], s[1], p); }

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

point reflection(const line &l, const point &p) {
  return p + 2.0 * (projection(l, p) - p);
}

point crosspointLL(const line &l, const line &m) {
  double A = cross(vec(l), vec(m));
  double B = cross(vec(l), l[1] - m[0]);
  if (abs(A) < eps)
    return l[9];
  return m[0] + B / A * vec(m);
}

bool intersectSP(const line &s, const point &p) {
  return abs(s[0] - p) + abs(s[1] - p) < abs(s[1] - s[0]) + eps;
}

bool intersectSS(const line &s, const line &t) {
  return (ccw(s, t[0]) * ccw(s, t[1]) < 0 && ccw(t, s[0]) * ccw(t, s[1]) < 0);
}

bool containGP(const polygon &g, const point &p) {
  /*
          for(int i=0; i<g.size(); i++)
          {
                  line edge(curr(g,i), next(g,i));
                  if(intersectSP(edge, p)) return true;
          }
  */
  bool in = false;
  for (int i = 0; i < g.size(); i++) {
    point a = curr(g, i) - p;
    point b = next(g, i) - p;
    if (imag(a) > imag(b))
      swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b)) {
      if (cross(a, b) < 0)
        in = !in;
    }
    if (cross(a, b) == 0 && dot(a, b) <= 0)
      return true;
  }
  return in;
}

bool containGS(const polygon &g, const line &l) {
  for (int i = 0; i < g.size(); i++) {
    if (intersectSS(l, line(curr(g, i), next(g, i))))
      return false;
  }
  return containGP(g, (l[0] + l[1]) / 2.0);
}

struct Node {
  point pos;
  vector<int> to;
  vector<double> cost;
};

struct Data {
  double d;
  int c, p;
  Data(double d, int c, int p) : d(d), c(c), p(p) {}
  bool operator<(const Data &x) const { return d > x.d; }
};

int main() {
  int N, M;
  while (cin >> N, N) {
    // 入力
    polygon building[100];

    for (int i = 0; i < N; i++) {
      cin >> M;
      for (int j = 0; j < M; j++) {
        int x, y;
        cin >> x >> y;
        building[i].push_back(point(x, y));
      }
    }

    int sx, sy, gx, gy;
    cin >> sx >> sy >> gx >> gy;

    int ax, ay, bx, by;
    cin >> ax >> ay >> bx >> by;

    point start(sx, sy);
    point goal(gx, gy);
    line mirror(point(ax, ay), point(bx, by));
    point mirror_start = reflection(mirror, start);
    point mirror_goal = reflection(mirror, goal);

    // 経路を含む建物の選択
    int b1 = -1, b2 = -1;
    for (int i = 0; i < N; i++) {
      if (containGP(building[i], start) && containGP(building[i], goal)) {
        b1 = i;
      }

      if (containGP(building[i], mirror_start) &&
          containGP(building[i], mirror_goal)) {
        b2 = i;
      }
    }

    if (b1 == -1 || b2 == -1) {
      cout << "impossible" << endl;
      continue;
    }

    for (int i = 0; i < building[b2].size(); i++) {
      building[b2][i] = reflection(mirror, building[b2][i]);
    }
    reverse(building[b2].begin(), building[b2].end());

    set<point> points;
    points.insert(start);
    points.insert(goal);
    for (int i = 0; i < building[b1].size(); i++) {
      points.insert(building[b1][i]);
    }
    for (int i = 0; i < building[b2].size(); i++) {
      points.insert(building[b2][i]);
    }

    int gsize = 2;
    Node nodes[102];
    for (set<point>::iterator it = points.begin(); it != points.end(); it++) {
      if (*it == start) {
        nodes[0].pos = *it;
      } else if (*it == goal) {
        nodes[1].pos = *it;
      } else {
        nodes[gsize++].pos = *it;
      }
    }

    for (int i = 0; i < gsize; i++)
      for (int j = 0; j < gsize; j++) {
        line edge(nodes[i].pos, nodes[j].pos);

        bool flag = false;
        for (int k = 0; k < gsize; k++) {
          if (k == i || k == j)
            continue;
          if (intersectSP(edge, nodes[k].pos)) {
            flag = true;
            break;
          }
        }

        if (flag)
          continue;

        if (containGS(building[b1], edge) && containGS(building[b2], edge)) {
          double d = abs(nodes[i].pos - nodes[j].pos);
          nodes[i].to.push_back(j);
          nodes[j].to.push_back(i);
          nodes[i].cost.push_back(d);
          nodes[j].cost.push_back(d);
        }
      }

    priority_queue<Data> q;
    bool visit[102] = {false};
    int prev[102] = {0};

    bool ok = false;
    q.push(Data(0, 0, 0));
    while (!q.empty()) {
      Data t = q.top();
      q.pop();

      visit[t.c] = true;
      prev[t.c] = t.p;
      if (t.c == 1) {
        /*
                                        int x = t.c;
                                        do
                                        {
                                                cout << nodes[x].pos << endl;
                                                x = prev[x];
                                        }
                                        while(x!=0);
        */
        ok = true;
        cout << t.d << endl;
        break;
      }

      for (int i = 0; i < nodes[t.c].to.size(); i++) {
        int to = nodes[t.c].to[i];
        if (visit[to])
          continue;
        q.push(Data(t.d + nodes[t.c].cost[i], to, t.c));
      }
    }

    if (!ok) {
      cout << "impossible" << endl;
    }
  }
}