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

#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;
using ll = long long;
using ld = double;
using C = pair<ll, ll>;
using L = pair<C, C>;

ll cross(const C a, const C b) {
  return a.first * b.second - a.second * b.first;
}
ll dot(const C a, const C b) { return a.first * b.first + a.second * b.second; }
ll normSq(const C a) { return a.first * a.first + a.second * a.second; }
ld norm(const L a) {
  const ll dx = a.first.first - a.second.first;
  const ll dy = a.first.second - a.second.second;
  return hypot(dx, dy);
}
int ccw(C a, C b, C c) {
  b = {b.first - a.first, b.second - a.second};
  c = {c.first - a.first, c.second - a.second};
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (normSq(b) < normSq(c))
    return -2; // a--b--c on line
  return 0;    // b--a--c on line
}
bool intersectSS(const L s, const L t) {
  return ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) <=
             0 and
         ccw(t.first, t.second, s.first) * ccw(t.first, t.second, s.second) <=
             0;
}
struct CostGraph {
  using T = ld;
  CostGraph(const int v) : V{v} { edge.resize(v); }
  struct Edge {
    Edge(const int from, const int to, const T cost)
        : from{from}, to{to}, cost{cost} {}
    const int from;
    const int to;
    const T cost;
    bool operator<(const Edge &e) const {
      return cost != e.cost ? cost < e.cost : to < e.to;
    }
  };
  void addEdge(const int from, const int to, const T cost) {
    edge[from].push_back(Edge{from, to, cost});
    edge[to].push_back(Edge{to, from, cost});
  }
  vector<vector<Edge>> edge;
  const int V;
};
void Dijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = 1e8;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}

int main() {
  int A, B;
  cin >> A >> B;
  vector<C> a(A);
  for (int i = 0; i < A; i++) {
    ll x, y;
    cin >> x >> y;
    a[i] = {x, y};
  }
  const L al = L{a[0], a[1]};
  vector<C> b(B);
  for (int i = 0; i < B; i++) {
    ll x, y;
    cin >> x >> y;
    b[i] = {x, y};
  }
  ld mini = 1e8;
  const L bl = L{b[0], b[1]};
  CostGraph ga(A);
  for (int i = 0; i < A; i++) {
    for (int j = i + 1; j < A; j++) {
      if (not intersectSS(bl, L{a[i], a[j]})) {
        ga.addEdge(i, j, norm(L{a[i], a[j]}));
      }
    }
  }
  vector<ld> ad(A);
  Dijkstra(ga, 0, ad);
  mini = min(mini, ad[1] + norm(bl));
  CostGraph gb(B);
  for (int i = 0; i < B; i++) {
    for (int j = i + 1; j < B; j++) {
      if (not intersectSS(al, L{b[i], b[j]})) {
        gb.addEdge(i, j, norm(L{b[i], b[j]}));
      }
    }
  }
  vector<ld> bd(B);
  Dijkstra(gb, 0, bd);
  mini = min(mini, bd[1] + norm(al));
  if (mini == 1e8) {
    cout << -1 << endl;
  } else {
    cout << fixed << setprecision(15) << mini << endl;
  }

  return 0;
}


Error: MLE

Fixed submission:

#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;
using ll = long long;
using ld = long double;
using C = pair<ll, ll>;
using L = pair<C, C>;

ll cross(const C a, const C b) {
  return a.first * b.second - a.second * b.first;
}
ll dot(const C a, const C b) { return a.first * b.first + a.second * b.second; }
ll normSq(const C a) { return a.first * a.first + a.second * a.second; }
ld norm(const L a) {
  const ll dx = a.first.first - a.second.first;
  const ll dy = a.first.second - a.second.second;
  return hypot(dx, dy);
}
int ccw(C a, C b, C c) {
  b = {b.first - a.first, b.second - a.second};
  c = {c.first - a.first, c.second - a.second};
  if (cross(b, c) > 0)
    return +1; // counter clockwise
  if (cross(b, c) < 0)
    return -1; // clockwise
  if (dot(b, c) < 0)
    return +2; // c--a--b on line
  if (normSq(b) < normSq(c))
    return -2; // a--b--c on line
  return 0;    // b--a--c on line
}
bool intersectSS(const L s, const L t) {
  return ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) <=
             0 and
         ccw(t.first, t.second, s.first) * ccw(t.first, t.second, s.second) <=
             0;
}
struct CostGraph {
  using T = ld;
  CostGraph(const int v) : V{v} {
    edge.resize(v);
    rev_edge.resize(v);
  }
  struct Edge {
    Edge(const int from, const int to, const T cost)
        : from{from}, to{to}, cost{cost} {}
    const int from;
    const int to;
    const T cost;
    bool operator<(const Edge &e) const {
      return cost != e.cost ? cost < e.cost : to < e.to;
    }
  };
  void addEdge(const int from, const int to, const T cost) {
    edge[from].push_back(Edge{from, to, cost});
    rev_edge[to].push_back(Edge(to, from, cost));
    edge[to].push_back(Edge{to, from, cost});
    rev_edge[from].push_back(Edge(from, to, cost));
  }
  vector<vector<Edge>> edge;
  vector<vector<Edge>> rev_edge;
  const int V;
};
void Dijkstra(const CostGraph &g, const int s, vector<CostGraph::T> &d) {
  using T = CostGraph::T;
  assert(s < g.V);
  assert(d.size() == g.V);
  using P = pair<T, int>;
  priority_queue<P, vector<P>, greater<P>> q;
  for (int i = 0; i < g.V; i++) {
    d[i] = 1e8;
  }
  d[s] = 0;
  q.push(make_pair(0, s));
  while (not q.empty()) {
    const P &p = q.top();
    const T cost = p.first;
    const int v = p.second;
    q.pop();
    if (d[v] < cost) {
      continue;
    }
    for (const auto &e : g.edge[v]) {
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        q.push(make_pair(d[e.to], e.to));
      }
    }
  }
}

int main() {
  int A, B;
  cin >> A >> B;
  vector<C> a(A);
  for (int i = 0; i < A; i++) {
    ll x, y;
    cin >> x >> y;
    a[i] = {x, y};
  }
  const L al = L{a[0], a[1]};
  vector<C> b(B);
  for (int i = 0; i < B; i++) {
    ll x, y;
    cin >> x >> y;
    b[i] = {x, y};
  }
  ld mini = 1e8;
  const L bl = L{b[0], b[1]};
  CostGraph ga(A);
  for (int i = 0; i < A; i++) {
    for (int j = i + 1; j < A; j++) {
      if (not intersectSS(bl, L{a[i], a[j]})) {
        ga.addEdge(i, j, norm(L{a[i], a[j]}));
      }
    }
  }
  vector<ld> ad(A);
  Dijkstra(ga, 0, ad);
  mini = min(mini, ad[1] + norm(bl));
  CostGraph gb(B);
  for (int i = 0; i < B; i++) {
    for (int j = i + 1; j < B; j++) {
      if (not intersectSS(al, L{b[i], b[j]})) {
        gb.addEdge(i, j, norm(L{b[i], b[j]}));
      }
    }
  }
  vector<ld> bd(B);
  Dijkstra(gb, 0, bd);
  mini = min(mini, bd[1] + norm(al));
  if (mini == 1e8) {
    cout << -1 << endl;
  } else {
    cout << fixed << setprecision(15) << mini << endl;
  }

  return 0;
}