Problem p01626 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <bits/stdc++.h>

using namespace std;

#define EPS 1e-8
#define equal(a, b) (fabs(a - b) < EPS)
#define lt(a, b) (a - b < -EPS)
#define MAX_N 100
#define MAX_P 500
#define INF 1e9

struct Point {
  double x, y;

  Point() {}
  Point(double x, double y) : x(x), y(y) {}

  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point operator*(const double &k) const { return Point(x * k, y * k); }
  Point operator/(const double &k) const { return Point(x / k, y / k); }
  bool operator<(const Point &p) const {
    if (!equal(x, p.x)) {
      return lt(x, p.x);
    } else {
      return lt(y, p.y);
    }
  }
  bool operator==(Point &p) const {
    if (equal(x, p.x) && equal(y, p.y)) {
      return true;
    }
    return false;
  }
};

double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
double cross(const Point &a, const Point &b) { return a.x * b.y - b.x * a.y; }
double norm(const Point &p) { return dot(p, p); }
double abs(const Point &p) { return sqrt(norm(p)); }
double dist(const Point &a, const Point &b) {
  return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}

#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
typedef Point Vector;

int ccw(const Point &p0, const Point &p1, const Point &p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (cross(a, b) > EPS) {
    return COUNTER_CLOCKWISE;
  }
  if (cross(a, b) < -EPS) {
    return CLOCKWISE;
  }
  if (dot(a, b) < -EPS) {
    return ONLINE_BACK;
  }
  if (norm(a) < norm(b)) {
    return ONLINE_FRONT;
  }
  return ON_SEGMENT;
}

typedef Point Vector;

struct Segment {
  Point s, t;
  Segment() {}
  Segment(Point s, Point t) : s(s), t(t) {}
  bool operator==(Segment &seg) const {
    if (s == seg.s && t == seg.t) {
      return true;
    }
    if (t == seg.s && s == seg.t) {
      return true;
    }
    return false;
  }
};

bool isIntersectSS(const Segment &a, const Segment &b) {
  Point s[2] = {a.s, a.t}, t[2] = {b.s, b.t};
  return (ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
          ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0);
}

Point crosspointSS(const Segment &a, const Segment &b) {
  Vector va = a.t - a.s, vb = b.t - b.s;
  double d = cross(vb, va);
  return a.s + va * cross(vb, b.t - a.s) * (1.0 / d);
}

struct Line {
  Point s, t;
  Line() {}
  Line(Point s, Point t) : s(s), t(t) {}
};

Point projection(const Line &l, const Point &p) {
  Vector b = l.t - l.s;
  double t = dot(p - l.s, b) / norm(b);
  return l.s + b * t;
}

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

#define curr(G, i) (G[i % G.size()])
#define next(G, i) (G[(i + 1) % G.size()])
typedef vector<Point> Polygon;

int containPP(const Polygon &pg, const Point &p) {
  int N = pg.size();
  bool in = false;
  for (int i = 0; i < N; i++) {
    Point a = curr(pg, i) - p, b = next(pg, i) - p;
    if (a.y > b.y) {
      swap(a, b);
    }
    if (a.y <= 0 && 0 < b.y && cross(a, b) < 0) {
      in = !in;
    }
    if (cross(a, b) == 0 && dot(a, b) <= 0) {
      return 1;
    }
  }
  return (in ? 2 : 0);
}

struct Data {
  Point p;
  double d;
  Data(Point p, double d) : p(p), d(d) {}
  bool operator<(const Data &data) const {
    if (!equal(d, data.d)) {
      return lt(d, data.d);
    } else {
      return p < data.p;
    }
  }
};

bool containPS(const Polygon &pg, Segment &s) {
  vector<Data> v;
  v.push_back(Data(s.s, 0));
  v.push_back(Data(s.t, dist(s.s, s.t)));
  set<Point> st;
  for (int i = 0; i < (int)pg.size(); i++) {
    Segment seg(curr(pg, i), next(pg, i));
    if (seg == s) {
      return true;
    }
    if (ccw(seg.s, seg.t, s.s) == 0 && ccw(seg.s, seg.t, s.t) == 0) {
      return true;
    }

    if (isIntersectSS(s, seg)) {
      Point cp = crosspointSS(s, seg);
      double d = dist(cp, s.s);
      if (st.find(cp) != st.end()) {
        continue;
      }
      st.insert(cp);
      v.push_back(Data(cp, d));
    }
  }
  sort(v.begin(), v.end());
  for (int i = 0; i < (int)v.size() - 1; i++) {
    Point cp = (v[i].p + v[i + 1].p) / 2.0;
    if (containPP(pg, cp) == 0) {
      return false;
    }
  }
  return true;
}

struct Edge {
  int to;
  double cost;
  Edge(int to, double cost) : to(to), cost(cost) {}
};

struct State {
  int v;
  double d;
  State(int v, double d) : v(v), d(d) {}
  bool operator<(const State &s) const { return d > s.d; }
};

Polygon L, R;
vector<Edge> G[MAX_P];

double dijkstra(int s, int t) {
  double dist[MAX_P];
  fill(dist, dist + MAX_P, INF);
  dist[s] = 0;
  priority_queue<State> Q;
  Q.push(State(s, 0));
  while (!Q.empty()) {
    State st = Q.top();
    Q.pop();
    int v = st.v;
    if (lt(dist[v], st.d)) {
      continue;
    }
    if (v == t) {
      return dist[t];
    }
    for (int i = 0; i < (int)G[v].size(); i++) {
      Edge e = G[v][i];
      if (lt(dist[v] + e.cost, dist[e.to])) {
        dist[e.to] = dist[v] + e.cost;
        Q.push(State(e.to, dist[e.to]));
      }
    }
  }
  return INF;
}

void init() {
  for (int i = 0; i < MAX_P; i++) {
    G[i].clear();
  }
}

int main() {
  int N;
  while (cin >> N, N) {
    init();
    Polygon b[MAX_N];
    for (int i = 0; i < N; i++) {
      int M;
      cin >> M;
      b[i].resize(M);
      for (int j = 0; j < M; j++) {
        cin >> b[i][j].x >> b[i][j].y;
      }
    }
    Point s, t;
    Line l;
    cin >> s.x >> s.y >> t.x >> t.y;
    cin >> l.s.x >> l.s.y >> l.t.x >> l.t.y;
    int n = -1;
    for (int i = 0; i < N; i++) {
      if (containPP(b[i], s) != 0) {
        n = i;
        L = b[n];
        break;
      }
    }
    int rn = -1;
    Point rs = reflection(l, s);
    for (int i = 0; i < N; i++) {
      if (containPP(b[i], rs) != 0) {
        rn = i;
        R = b[rn];
        break;
      }
    }
    Point rt = reflection(l, t);
    if (n == -1 || rn == -1 || containPP(R, rt) == 0) {
      cout << "impossible" << endl;
      continue;
    }

    int size = L.size();
    int rsize = R.size();
    int src, dst;
    for (int i = 0; i < size; i++) {
      L[i] = reflection(l, L[i]);
    }
    set<Point> st;
    for (int i = 0; i < size; i++) {
      if (st.find(L[i]) == st.end()) {
        st.insert(L[i]);
      }
    }

    for (int i = 0; i < rsize; i++) {
      if (st.find(R[i]) == st.end()) {
        st.insert(R[i]);
      }
    }
    s = reflection(l, s);
    t = reflection(l, t);
    if (st.find(s) == st.end()) {
      st.insert(s);
    }
    if (st.find(t) == st.end()) {
      st.insert(t);
    }
    vector<Point> vec;
    for (auto it = st.begin(); it != st.end(); ++it) {
      vec.push_back(*it);
    }
    size = vec.size();
    for (int i = 0; i < size; i++) {
      for (int j = i + 1; j < size; j++) {
        Segment seg(vec[i], vec[j]);
        if (containPS(L, seg) && containPS(R, seg)) {
          double d = dist(vec[i], vec[j]);
          G[i].push_back(Edge(j, d));
          G[j].push_back(Edge(i, d));
        }
      }
      if (s == vec[i]) {
        src = i;
      }
      if (t == vec[i]) {
        dst = i;
      }
    }
    double res = dijkstra(src, dst);
    if (res == INF) {
      cout << "impossible" << endl;
    } else {
      printf("%.10f\\n", res);
    }
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

#define EPS 1e-10
#define equal(a, b) (fabs(a - b) < EPS)
#define lt(a, b) (a - b < -EPS)
#define MAX_N 100
#define MAX_P 500
#define INF 1e9

struct Point {
  double x, y;

  Point() {}
  Point(double x, double y) : x(x), y(y) {}

  Point operator+(const Point &p) const { return Point(x + p.x, y + p.y); }
  Point operator-(const Point &p) const { return Point(x - p.x, y - p.y); }
  Point operator*(const double &k) const { return Point(x * k, y * k); }
  Point operator/(const double &k) const { return Point(x / k, y / k); }
  bool operator<(const Point &p) const {
    if (!equal(x, p.x)) {
      return lt(x, p.x);
    } else {
      return lt(y, p.y);
    }
  }
  bool operator==(Point &p) const {
    if (equal(x, p.x) && equal(y, p.y)) {
      return true;
    }
    return false;
  }
};

double dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }
double cross(const Point &a, const Point &b) { return a.x * b.y - b.x * a.y; }
double norm(const Point &p) { return dot(p, p); }
double abs(const Point &p) { return sqrt(norm(p)); }
double dist(const Point &a, const Point &b) {
  return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}

#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
typedef Point Vector;

int ccw(const Point &p0, const Point &p1, const Point &p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (cross(a, b) > EPS) {
    return COUNTER_CLOCKWISE;
  }
  if (cross(a, b) < -EPS) {
    return CLOCKWISE;
  }
  if (dot(a, b) < -EPS) {
    return ONLINE_BACK;
  }
  if (norm(a) < norm(b)) {
    return ONLINE_FRONT;
  }
  return ON_SEGMENT;
}

typedef Point Vector;

struct Segment {
  Point s, t;
  Segment() {}
  Segment(Point s, Point t) : s(s), t(t) {}
  bool operator==(Segment &seg) const {
    if (s == seg.s && t == seg.t) {
      return true;
    }
    if (t == seg.s && s == seg.t) {
      return true;
    }
    return false;
  }
};

bool isIntersectSS(const Segment &a, const Segment &b) {
  Point s[2] = {a.s, a.t}, t[2] = {b.s, b.t};
  return (ccw(s[0], s[1], t[0]) * ccw(s[0], s[1], t[1]) <= 0 &&
          ccw(t[0], t[1], s[0]) * ccw(t[0], t[1], s[1]) <= 0);
}

Point crosspointSS(const Segment &a, const Segment &b) {
  Vector va = a.t - a.s, vb = b.t - b.s;
  double d = cross(vb, va);
  return a.s + va * cross(vb, b.t - a.s) * (1.0 / d);
}

struct Line {
  Point s, t;
  Line() {}
  Line(Point s, Point t) : s(s), t(t) {}
};

Point projection(const Line &l, const Point &p) {
  Vector b = l.t - l.s;
  double t = dot(p - l.s, b) / norm(b);
  return l.s + b * t;
}

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

#define curr(G, i) (G[i % G.size()])
#define next(G, i) (G[(i + 1) % G.size()])
typedef vector<Point> Polygon;

int containPP(const Polygon &pg, const Point &p) {
  int N = pg.size();
  bool in = false;
  for (int i = 0; i < N; i++) {
    Point a = curr(pg, i) - p, b = next(pg, i) - p;
    if (a.y > b.y) {
      swap(a, b);
    }
    if (a.y <= 0 && 0 < b.y && cross(a, b) < 0) {
      in = !in;
    }
    if (cross(a, b) == 0 && dot(a, b) <= 0) {
      return 1;
    }
  }
  return (in ? 2 : 0);
}

struct Data {
  Point p;
  double d;
  Data(Point p, double d) : p(p), d(d) {}
  bool operator<(const Data &data) const { return lt(d, data.d); }
};

bool containPS(const Polygon &pg, Segment &s) {
  Point p1 = s.s, p2 = s.t;
  vector<Point> res;
  const int N = 5000;
  for (int i = 0; i < N; i++) {
    double x = p1.x + i * (p2.x - p1.x) / N;
    double y = p1.y + i * (p2.y - p1.y) / N;
    Point np(x, y);
    if (containPP(pg, np) == 0) {
      return false;
    }
  }
  return true;
}

struct Edge {
  int to;
  double cost;
  Edge(int to, double cost) : to(to), cost(cost) {}
};

struct State {
  int v;
  double d;
  State(int v, double d) : v(v), d(d) {}
  bool operator<(const State &s) const { return d > s.d; }
};

Polygon L, R;
vector<Edge> G[MAX_P];

double dijkstra(int s, int t) {
  double dist[MAX_P];
  fill(dist, dist + MAX_P, INF);
  dist[s] = 0;
  priority_queue<State> Q;
  Q.push(State(s, 0));
  while (!Q.empty()) {
    State st = Q.top();
    Q.pop();
    int v = st.v;
    if (lt(dist[v], st.d)) {
      continue;
    }
    if (v == t) {
      return dist[t];
    }
    for (int i = 0; i < (int)G[v].size(); i++) {
      Edge e = G[v][i];
      if (lt(dist[v] + e.cost, dist[e.to])) {
        dist[e.to] = dist[v] + e.cost;
        Q.push(State(e.to, dist[e.to]));
      }
    }
  }
  return INF;
}

void init() {
  for (int i = 0; i < MAX_P; i++) {
    G[i].clear();
  }
}

int main() {
  int N;
  while (cin >> N, N) {
    init();
    Polygon b[MAX_N];
    for (int i = 0; i < N; i++) {
      int M;
      cin >> M;
      b[i].resize(M);
      for (int j = 0; j < M; j++) {
        cin >> b[i][j].x >> b[i][j].y;
      }
    }
    Point s, t;
    Line l;
    cin >> s.x >> s.y >> t.x >> t.y;
    cin >> l.s.x >> l.s.y >> l.t.x >> l.t.y;
    int n = -1;
    for (int i = 0; i < N; i++) {
      if (containPP(b[i], s) != 0) {
        n = i;
        L = b[n];
        break;
      }
    }
    int rn = -1;
    Point rs = reflection(l, s);
    for (int i = 0; i < N; i++) {
      if (containPP(b[i], rs) != 0) {
        rn = i;
        R = b[rn];
        break;
      }
    }
    Point rt = reflection(l, t);
    if (n == -1 || N == 1 || rn == -1 || containPP(R, rt) == 0) {
      cout << "impossible" << endl;
      continue;
    }

    int size = L.size();
    int rsize = R.size();
    int src, dst;
    for (int i = 0; i < size; i++) {
      L[i] = reflection(l, L[i]);
    }
    set<Point> st;
    for (int i = 0; i < size; i++) {
      if (st.find(L[i]) == st.end()) {
        st.insert(L[i]);
      }
    }
    for (int i = 0; i < rsize; i++) {
      if (st.find(R[i]) == st.end()) {
        st.insert(R[i]);
      }
    }
    s = reflection(l, s);
    t = reflection(l, t);
    if (st.find(s) == st.end()) {
      st.insert(s);
    }
    if (st.find(t) == st.end()) {
      st.insert(t);
    }
    vector<Point> vec;
    for (auto it = st.begin(); it != st.end(); ++it) {
      vec.push_back(*it);
    }
    size = vec.size();
    for (int i = 0; i < size; i++) {
      for (int j = i + 1; j < size; j++) {
        Segment seg(vec[i], vec[j]);
        if (containPS(L, seg) && containPS(R, seg)) {
          double d = dist(vec[i], vec[j]);
          G[i].push_back(Edge(j, d));
          G[j].push_back(Edge(i, d));
        }
      }
      if (s == vec[i]) {
        src = i;
      }
      if (t == vec[i]) {
        dst = i;
      }
    }
    double res = dijkstra(src, dst);
    if (res == INF) {
      cout << "impossible" << endl;
    } else {
      printf("%.10f\\n", res);
    }
  }
  return 0;
}