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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const double EPS = 1e-8;

typedef complex<double> P;
namespace std {
bool operator<(const P &a, const P &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std
double cross(const P &a, const P &b) { return imag(conj(a) * b); }
double dot(const P &a, const P &b) { return real(conj(a) * b); }

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  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 (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}

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

bool intersectLL(const L &l, const L &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
}

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

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS)
    return m[0]; // same line
  if (abs(A) < EPS)
    assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) <
         EPS; // triangle inequality
}

struct Edge {
  int from, to;
  double cost;
};

typedef vector<vector<Edge>> Graph;

Graph segment_arrangement(const std::vector<L> &ss, std::vector<P> &ps) {
  for (int i = 0; i < (int)ss.size(); ++i) { // O(n^2)
    ps.push_back(ss[i][0]);
    ps.push_back(ss[i][1]);
    for (int j = i + 1; j < (int)ss.size(); ++j)
      if (intersectSS(ss[i], ss[j]))
        ps.push_back(crosspointLL(ss[i], ss[j]));
  }
  std::sort(ps.begin(), ps.end());
  ps.erase(std::unique(ps.begin(), ps.end()), ps.end());
  Graph g(ps.size());
  for (int i = 0; i < (int)ss.size(); ++i) {
    std::vector<std::pair<double, int>> list;
    for (int j = 0; j < (int)ps.size(); ++j)
      if (intersectSP(ss[i], ps[j]))
        list.push_back(std::make_pair(norm(ss[i][0] - ps[j]), j));
    std::sort(list.begin(), list.end());
    for (int j = 0; j + 1 < (int)list.size(); ++j) {
      int a = list[j].second, b = list[j + 1].second;
      double len = abs(ps[a] - ps[b]);
      g[a].push_back({a, b, len});
      g[b].push_back({b, a, len});
    }
  }
  return g;
}

typedef pair<double, int> State;
const double INF = 1e18;
bool sign[200];

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
#ifdef LOCAL
  std::ifstream in("in");
  std::cin.rdbuf(in.rdbuf());
#endif

  int n;
  while (cin >> n, n) {
    P start, goal;
    {
      int x, y;
      cin >> x >> y;
      start = P(x, y);
      cin >> x >> y;
      goal = P(x, y);
    }
    vector<L> ls(n);
    for (int i = 0; i < n; i++) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      ls[i] = L(P(x1, y1), P(x2, y2));
    }
    vector<L> seg;
    for (int i = 0; i < n; i++) {
      sign[i] = 0;
      int intersect[2] = {0};
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (intersectSP(ls[j], ls[i][0]))
          intersect[0] = 1;
        if (intersectSP(ls[j], ls[i][1]))
          intersect[1] = 1;
      }
      assert(intersect[0] + intersect[1] >= 1);
      if (intersect[0] + intersect[1] == 1) {
        sign[i] = 1;
        // cout << "sign " << i << endl;
      } else {
        seg.push_back(ls[i]);
      }
    }

    vector<P> ps;
    auto G = segment_arrangement(seg, ps);
    map<P, int> idxMap;
    for (int i = 0; i < ps.size(); i++) {
      idxMap[ps[i]] = i;
    }

    set<pair<int, int>> NG;
    for (int i = 0; i < ps.size(); i++) {
      for (auto e : G[i]) {
        int u = i, v = e.to;
        P p0 = ps[u], p1 = ps[v];
        for (int j = 0; j < n; j++) {
          if (!sign[j])
            continue;
          int onIdx = -1;
          for (int k = 0; k < 2; k++) {
            P sp = ls[j][k];
            if (ccw(p0, sp, p1) == -2 || ccw(p1, sp, p0) == -2) {
              onIdx = k;
              break;
            }
          }
          if (onIdx == -1)
            continue;

          P sp0 = ls[j][onIdx], sp1 = ls[j][1 - onIdx];
          P v1 = p1 - p0, v2 = sp1 - sp0;
          int d = dot(v1, v2);
          if (d >= 0) {
            NG.insert({u, v});
            // cout << "NG " << (int)ps[u].real() << " " << (int)ps[u].imag() <<
            // " -> "
            //<< (int)ps[v].real() << " " << (int)ps[v].imag() << endl;
          }
        }
      }
    }

    vector<double> dist(ps.size(), INF);
    vector<int> pre(ps.size(), -1);
    priority_queue<State, vector<State>, greater<State>> q;
    q.push({0, idxMap[start]});
    dist[idxMap[start]] = 0;
    while (q.size()) {
      int v = q.top().second;
      double d = q.top().first;
      q.pop();
      if (dist[v] < d)
        continue;
      for (auto e : G[v]) {
        if (NG.count({v, e.to}))
          continue;
        double nd = d + abs(ps[e.to] - ps[v]);
        if (dist[e.to] > nd) {
          dist[e.to] = nd;
          pre[e.to] = v;
          q.push({nd, e.to});
        }
      }
    }

    if (dist[idxMap[goal]] == INF) {
      cout << -1 << endl;
      continue;
    }

    int cur = idxMap[goal];
    vector<int> path;
    while (true) {
      path.push_back(cur);
      if (cur == idxMap[start])
        break;
      cur = pre[cur];
    }
    reverse(path.begin(), path.end());
    for (auto pp : path) {
      cout << (int)ps[pp].real() << " " << (int)ps[pp].imag() << endl;
    }
    cout << 0 << endl;
  }
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const double EPS = 1e-8;

typedef complex<double> P;
namespace std {
bool operator<(const P &a, const P &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std
double cross(const P &a, const P &b) { return imag(conj(a) * b); }
double dot(const P &a, const P &b) { return real(conj(a) * b); }

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  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 (norm(b) < norm(c))
    return -2; // a--b--c on line
  return 0;
}

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

bool intersectLL(const L &l, const L &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
}

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

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS)
    return m[0]; // same line
  if (abs(A) < EPS)
    assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0] - p) + abs(s[1] - p) - abs(s[1] - s[0]) <
         EPS; // triangle inequality
}

struct Edge {
  int from, to;
  double cost;
};

typedef vector<vector<Edge>> Graph;

Graph segment_arrangement(const std::vector<L> &ss, std::vector<P> &ps) {
  for (int i = 0; i < (int)ss.size(); ++i) { // O(n^2)
    ps.push_back(ss[i][0]);
    ps.push_back(ss[i][1]);
    for (int j = i + 1; j < (int)ss.size(); ++j)
      if (intersectSS(ss[i], ss[j]))
        ps.push_back(crosspointLL(ss[i], ss[j]));
  }
  std::sort(ps.begin(), ps.end());
  ps.erase(std::unique(ps.begin(), ps.end()), ps.end());
  Graph g(ps.size());
  for (int i = 0; i < (int)ss.size(); ++i) {
    std::vector<std::pair<double, int>> list;
    for (int j = 0; j < (int)ps.size(); ++j)
      if (intersectSP(ss[i], ps[j]))
        list.push_back(std::make_pair(norm(ss[i][0] - ps[j]), j));
    std::sort(list.begin(), list.end());
    for (int j = 0; j + 1 < (int)list.size(); ++j) {
      int a = list[j].second, b = list[j + 1].second;
      double len = abs(ps[a] - ps[b]);
      g[a].push_back({a, b, len});
      g[b].push_back({b, a, len});
    }
  }
  return g;
}

typedef pair<double, int> State;
const double INF = 1e18;
bool sign[200];
int NG[4000][4000];

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
#ifdef LOCAL
  std::ifstream in("in");
  std::cin.rdbuf(in.rdbuf());
#endif

  int n;
  while (cin >> n, n) {
    P start, goal;
    {
      int x, y;
      cin >> x >> y;
      start = P(x, y);
      cin >> x >> y;
      goal = P(x, y);
    }
    vector<L> ls(n);
    for (int i = 0; i < n; i++) {
      int x1, y1, x2, y2;
      cin >> x1 >> y1 >> x2 >> y2;
      ls[i] = L(P(x1, y1), P(x2, y2));
    }
    vector<L> seg;
    for (int i = 0; i < n; i++) {
      sign[i] = 0;
      int intersect[2] = {0};
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (intersectSP(ls[j], ls[i][0]))
          intersect[0] = 1;
        if (intersectSP(ls[j], ls[i][1]))
          intersect[1] = 1;
      }
      assert(intersect[0] + intersect[1] >= 1);
      if (intersect[0] + intersect[1] == 1) {
        sign[i] = 1;
        // cout << "sign " << i << endl;
      } else {
        seg.push_back(ls[i]);
      }
    }

    vector<P> ps;
    auto G = segment_arrangement(seg, ps);
    map<P, int> idxMap;
    for (int i = 0; i < ps.size(); i++) {
      idxMap[ps[i]] = i;
    }

    memset(NG, 0, sizeof NG);
    for (int i = 0; i < ps.size(); i++) {
      for (auto e : G[i]) {
        int u = i, v = e.to;
        P p0 = ps[u], p1 = ps[v];
        for (int j = 0; j < n; j++) {
          if (!sign[j])
            continue;
          int onIdx = -1;
          for (int k = 0; k < 2; k++) {
            P sp = ls[j][k];
            if (ccw(p0, sp, p1) == -2 || ccw(p1, sp, p0) == -2) {
              onIdx = k;
              break;
            }
          }
          if (onIdx == -1)
            continue;

          P sp0 = ls[j][onIdx], sp1 = ls[j][1 - onIdx];
          P v1 = p1 - p0, v2 = sp1 - sp0;
          int d = dot(v1, v2);
          if (d >= 0) {
            NG[u][v] = 1;
            // cout << "NG " << (int)ps[u].real() << " " << (int)ps[u].imag() <<
            // " -> "
            //<< (int)ps[v].real() << " " << (int)ps[v].imag() << endl;
          }
        }
      }
    }

    vector<double> dist(ps.size(), INF);
    vector<int> pre(ps.size(), -1);
    priority_queue<State, vector<State>, greater<State>> q;
    q.push({0, idxMap[start]});
    dist[idxMap[start]] = 0;
    while (q.size()) {
      int v = q.top().second;
      double d = q.top().first;
      q.pop();
      if (dist[v] < d)
        continue;
      for (auto e : G[v]) {
        if (NG[v][e.to])
          continue;
        double nd = d + abs(ps[e.to] - ps[v]);
        if (dist[e.to] > nd) {
          dist[e.to] = nd;
          pre[e.to] = v;
          q.push({nd, e.to});
        }
      }
    }

    if (dist[idxMap[goal]] == INF) {
      cout << -1 << endl;
      continue;
    }

    int cur = idxMap[goal];
    vector<int> path;
    while (true) {
      path.push_back(cur);
      if (cur == idxMap[start])
        break;
      cur = pre[cur];
    }
    reverse(path.begin(), path.end());
    for (auto pp : path) {
      cout << (int)ps[pp].real() << " " << (int)ps[pp].imag() << endl;
    }
    cout << 0 << endl;
  }
}