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

#include <algorithm>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <tuple>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define RREP(i, n) for (int i = (int)n - 1; i >= 0; i--)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define RFOR(i, c)                                                             \\
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); ++i)
#define ALL(c) (c).begin(), (c).end()

typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<int, pair<int, int>> pipii;
typedef vector<int> vi;

const int MOD = 1e9 + 7;

typedef tuple<double, double> mytuple;

#define EPS 1e-8
typedef complex<double> Point;
namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
Point operator/(const Point &p, const double &a) {
  return Point(real(p) / a, imag(p) / a);
}
Point operator*(const Point &p, const double &a) {
  return Point(real(p) * a, imag(p) * a);
}
bool operator==(const Point &a, const Point &b) {
  return real(a) == real(b) && imag(a) == imag(b);
}
} // namespace std
typedef vector<Point> Polygon;
struct Line : public vector<Point> {
  Line() {}
  Line(const Point &a, const Point &b) {
    push_back(a);
    push_back(b);
  }
};

double dot(const Point &a, const Point &b) { return real(conj(a) * b); }

double cross(const Point &a, const Point &b) { return imag(conj(a) * b); }

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0)
    return +1; // ccw
  if (cross(b, c) < 0)
    return -1; // cw
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;    // a--c--b or (c=b)
}

bool intersectSS(const Line &s, const Line &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;
}

bool intersectLL(const Line &l, const Line &m) {
  return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
         abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}

typedef double Weight;
const Weight INF = 1e9;
struct Edge {
  int src, dst;
  Weight weight;
  int rev;
  Edge(int f, int t, Weight c, int rev = 0)
      : src(f), dst(t), weight(c), rev(rev) {}
  bool operator<(const Edge &re) const { return weight > re.weight; }
};
typedef vector<vector<Edge>> Graph;
void add_edge(Graph &G, int s, int t, Weight cap) {
  G[s].push_back(Edge(s, t, cap, G[t].size()));
}
void shortestPath(const Graph &g, int s, vector<Weight> &dist,
                  vector<int> &prev) {
  int n = g.size();
  dist.assign(n, INF);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q;
  for (Q.push(Edge(-2, s, 0)); !Q.empty();) {
    Edge e = Q.top();
    Q.pop();
    if (prev[e.dst] != -1)
      continue;
    prev[e.dst] = e.src;
    FOR(f, g[e.dst]) {
      if (dist[f->dst] > e.weight + f->weight) {
        dist[f->dst] = e.weight + f->weight;
        Q.push(Edge(f->src, f->dst, e.weight + f->weight));
      }
    }
  }
}

double dist(Line &l) { return abs(l[1] - l[0]); }

int main(void) {
  int na, nb;
  cin >> na >> nb;
  vector<Point> aP, bP;
  REP(i, na) {
    double x, y;
    cin >> x >> y;
    aP.push_back(Point(x, y));
  }
  REP(i, nb) {
    double x, y;
    cin >> x >> y;
    bP.push_back(Point(x, y));
  }

  Graph g(na);
  REP(i, na) {
    for (int j = i + 1; j < na; j++) {
      Line b = Line((bP[0]), (bP[1]));
      Line a = Line((aP[i]), (aP[j]));
      if (!intersectSS(a, b)) {
        add_edge(g, i, j, dist(a));
        add_edge(g, j, i, dist(a));
      }
    }
  }
  vector<Weight> di;
  vi path;
  shortestPath(g, 0, di, path);
  Line b = Line((bP[0]), (bP[1]));
  double l = dist(b) + di[1];

  double ans = INF;

  g.clear();
  g.resize(nb);
  REP(i, nb) {
    for (int j = i + 1; j < nb; j++) {
      Line b = Line((aP[0]), (aP[1]));
      Line a = Line((bP[i]), (bP[j]));
      if (!intersectSS(a, b)) {
        add_edge(g, i, j, dist(a));
        add_edge(g, j, i, dist(a));
      }
    }
  }
  vector<Weight> dist2;
  vi path2;
  shortestPath(g, 0, dist2, path2);
  Line a = Line((aP[0]), (aP[1]));
  double r = dist(a) + dist2[1];

  if (!intersectSS(a, b)) {
    printf("%.10lf", dist(a) + dist(b));
  } else if (min(l, r) < INF - EPS) {
    printf("%.10lf", min(l, r));
  } else
    cout << -1 << endl;

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <tuple>
#include <vector>
using namespace std;

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define RREP(i, n) for (int i = (int)n - 1; i >= 0; i--)
#define FOR(i, c)                                                              \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define RFOR(i, c)                                                             \\
  for (__typeof((c).rbegin()) i = (c).rbegin(); i != (c).rend(); ++i)
#define ALL(c) (c).begin(), (c).end()

typedef long long int ll;
typedef pair<int, int> pii;
typedef pair<int, pair<int, int>> pipii;
typedef vector<int> vi;

const int MOD = 1e9 + 7;

typedef tuple<double, double> mytuple;

#define EPS 1e-8
typedef complex<double> Point;
namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
Point operator/(const Point &p, const double &a) {
  return Point(real(p) / a, imag(p) / a);
}
Point operator*(const Point &p, const double &a) {
  return Point(real(p) * a, imag(p) * a);
}
bool operator==(const Point &a, const Point &b) {
  return real(a) == real(b) && imag(a) == imag(b);
}
} // namespace std
typedef vector<Point> Polygon;
struct Line : public vector<Point> {
  Line() {}
  Line(const Point &a, const Point &b) {
    push_back(a);
    push_back(b);
  }
};

double dot(const Point &a, const Point &b) { return real(conj(a) * b); }

double cross(const Point &a, const Point &b) { return imag(conj(a) * b); }

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > 0)
    return +1; // ccw
  if (cross(b, c) < 0)
    return -1; // cw
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;    // a--c--b or (c=b)
}

bool intersectSS(const Line &s, const Line &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;
}

bool intersectLL(const Line &l, const Line &m) {
  return abs(cross(l[1] - l[0], m[1] - m[0])) > EPS || // non-parallel
         abs(cross(l[1] - l[0], m[0] - l[0])) < EPS;   // same line
}

typedef double Weight;
const Weight INF = 1e9;
struct Edge {
  int src, dst;
  Weight weight;
  int rev;
  Edge(int f, int t, Weight c, int rev = 0)
      : src(f), dst(t), weight(c), rev(rev) {}
  bool operator<(const Edge &re) const { return weight > re.weight; }
};
typedef vector<vector<Edge>> Graph;
void add_edge(Graph &G, int s, int t, Weight cap) {
  G[s].push_back(Edge(s, t, cap, G[t].size()));
}
void shortestPath(const Graph &g, int s, vector<Weight> &dist,
                  vector<int> &prev) {
  int n = g.size();
  dist.assign(n, INF);
  dist[s] = 0;
  prev.assign(n, -1);
  priority_queue<Edge> Q;
  for (Q.push(Edge(-2, s, 0)); !Q.empty();) {
    Edge e = Q.top();
    Q.pop();
    if (prev[e.dst] != -1)
      continue;
    prev[e.dst] = e.src;
    FOR(f, g[e.dst]) {
      if (dist[f->dst] > e.weight + f->weight) {
        dist[f->dst] = e.weight + f->weight;
        Q.push(Edge(f->src, f->dst, e.weight + f->weight));
      }
    }
  }
}

double dist(Line &l) { return abs(l[1] - l[0]); }

int main(void) {
  int na, nb;
  while (cin >> na >> nb, na || nb) {
    vector<Point> aP, bP;
    REP(i, na) {
      double x, y;
      cin >> x >> y;
      aP.push_back(Point(x, y));
    }
    REP(i, nb) {
      double x, y;
      cin >> x >> y;
      bP.push_back(Point(x, y));
    }

    Graph g(na);
    REP(i, na) {
      for (int j = i + 1; j < na; j++) {
        Line b = Line((bP[0]), (bP[1]));
        Line a = Line((aP[i]), (aP[j]));
        if (!intersectSS(a, b)) {
          add_edge(g, i, j, dist(a));
          add_edge(g, j, i, dist(a));
        }
      }
    }
    vector<Weight> di;
    vi path;
    shortestPath(g, 0, di, path);
    Line b = Line((bP[0]), (bP[1]));
    double l = dist(b) + di[1];

    double ans = INF;

    g.resize(nb);
    REP(i, nb) {
      for (int j = i + 1; j < nb; j++) {
        Line b = Line((aP[0]), (aP[1]));
        Line a = Line((bP[i]), (bP[j]));
        if (!intersectSS(a, b)) {
          add_edge(g, i, j, dist(a));
          add_edge(g, j, i, dist(a));
        }
      }
    }
    vector<Weight> dist2;
    vi path2;
    shortestPath(g, 0, dist2, path2);
    Line a = Line((aP[0]), (aP[1]));
    double r = dist(a) + dist2[1];

    if (!intersectSS(a, b)) {
      printf("%.10lf", dist(a) + dist(b));
    } else if (min(l, r) < INF - EPS) {
      printf("%.10lf", min(l, r));
    } else
      cout << -1 << endl;
  }

  return 0;
}