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

#include <algorithm>
#include <complex>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef complex<double> P;
struct L {
  P p, q;
  L(P p, P q) : p(p), q(q) {}
};

class Node {
public:
  int p, q;
  double cost;
  Node(int p, int q, double cost) : p(p), q(q), cost(cost) {}
  bool operator<(const Node &nd) const { return cost > nd.cost; }
};

typedef vector<vector<Node>> graph;

const double EPS = 1e-6;

bool comp(const P &a, const P &b) {
  return make_pair(a.real(), a.imag()) < make_pair(b.real(), b.imag());
}

template <class T> inline const T &abs(const T &a) { return a > 0 ? a : -a; }

double dot(P a, P b) { return real(conj(a) * b); }
double cross(P a, P b) { return imag(conj(a) * b); }

bool spIntersect(L l, P p) {
  return abs(abs(l.p - p) + abs(p - l.q) - abs(l.p - l.q)) < EPS;
}

bool checkSign(L l, const vector<L> &sign) {
  for (int i = 0; i < sign.size(); i++) {
    L sg = sign[i];
    for (int j = 0; j < 2; j++) {
      if (spIntersect(l, sg.p) && dot(l.q - l.p, sg.q - sg.p) > -EPS)
        return false;
      swap(sg.p, sg.q);
    }
  }
  return true;
}

graph makeGraph(vector<P> &pt, const vector<L> &road, const vector<L> &sign) {
  for (int i = 0; i < road.size(); i++) {
    pt.push_back(road[i].p);
    pt.push_back(road[i].q);
  }
  sort(pt.begin(), pt.end(), comp);
  pt.erase(unique(pt.begin(), pt.end()), pt.end());
  graph g(pt.size());
  for (int i = 0; i < road.size(); i++) {
    vector<pair<double, int>> vp;
    for (int j = 0; j < pt.size(); j++)
      if (spIntersect(road[i], pt[j]))
        vp.push_back(make_pair(abs(road[i].p - pt[j]), j));
    sort(vp.begin(), vp.end());
    for (int j = 0; j + 1 < vp.size(); j++) {
      int a = vp[j].second, b = vp[j + 1].second;
      if (checkSign(L(pt[a], pt[b]), sign))
        g[a].push_back(Node(a, b, abs(pt[a] - pt[b])));
      if (checkSign(L(pt[b], pt[a]), sign))
        g[b].push_back(Node(b, a, abs(pt[a] - pt[b])));
    }
  }
  return g;
}

void dijkstra(const graph &g, int s, int t, const vector<P> &vp) {
  int n = g.size();
  vector<double> cost(n, 1e12);
  cost[s] = 0.0;
  vector<int> prev(n, -1);
  priority_queue<Node> qu;
  qu.push(Node(-1, s, 0.0));
  while (!qu.empty()) {
    Node nd = qu.top();
    qu.pop();
    int pos = nd.q;
    if (prev[pos] != nd.p)
      continue;
    if (pos == t) {
      vector<int> path;
      for (int p = t; p != -1; p = prev[p])
        path.push_back(p);
      reverse(path.begin(), path.end());
      for (int i = 0; i < path.size(); i++)
        printf("%d %d\\n", int(real(vp[path[i]]) + EPS),
               int(imag(vp[path[i]]) + EPS));
      puts("0");
      return;
    }
    for (int i = 0; i < g[pos].size(); i++) {
      int next = g[pos][i].q;
      if (cost[pos] + g[pos][i].cost < cost[next]) {
        cost[next] = cost[pos] + g[pos][i].cost;
        prev[next] = pos;
        qu.push(Node(pos, next, cost[next]));
      }
    }
  }
  puts("-1");
}

int main() {
  int n;
  while (cin >> n, n) {
    int x1, y1, x2, y2;
    cin >> x1 >> y1 >> x2 >> y2;
    P start = P(x1, y1), goal = P(x2, y2);
    vector<L> vl, road, sign;
    for (int i = 0; i < n; i++) {
      cin >> x1 >> y1 >> x2 >> y2;
      vl.push_back(L(P(x1, y1), P(x2, y2)));
    }
    for (int i = 0; i < n; i++) {
      bool bp = false, bq = false;
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (spIntersect(vl[j], vl[i].p))
          bp = true;
        if (spIntersect(vl[j], vl[i].q))
          bq = true;
      }
      if (bp & bq)
        road.push_back(vl[i]);
      else
        sign.push_back(vl[i]);
    }
    vector<P> vp;
    graph g = makeGraph(vp, road, sign);
    int sidx, gidx;
    for (int i = 0; i < vp.size(); i++) {
      if (abs(start - vp[i]) < EPS)
        sidx = i;
      if (abs(goal - vp[i]) < EPS)
        gidx = i;
    }
    dijkstra(g, sidx, gidx, vp);
  }
}

Error: MLE

Fixed submission:

// 2007ツアツジツアツ地ツ凝ヲツ予ツ選E : Geometric Map

#include <algorithm>
#include <complex>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

typedef complex<double> P;
struct L {
  P p, q;
  L(P p, P q) : p(p), q(q) {}
};

class Node {
public:
  int pos;
  double cost;
  Node(int pos, double cost) : pos(pos), cost(cost) {}
  bool operator<(const Node &nd) const { return cost > nd.cost; }
};

typedef vector<vector<Node>> graph;

const double EPS = 1e-8;

bool comp(const P &a, const P &b) {
  return make_pair(a.real(), a.imag()) < make_pair(b.real(), b.imag());
}

template <class T> inline const T &abs(const T &a) { return a > 0 ? a : -a; }

double dot(P a, P b) { return real(conj(a) * b); }
double cross(P a, P b) { return imag(conj(a) * b); }

bool spIntersect(L l, P p) {
  return abs(abs(l.p - p) + abs(p - l.q) - abs(l.p - l.q)) < EPS;
}

bool checkSign(L l, const vector<L> &sign) {
  for (int i = 0; i < sign.size(); i++) {
    L sg = sign[i];
    for (int j = 0; j < 2; j++) {
      if (spIntersect(l, sg.p))
        return dot(l.q - l.p, sg.q - sg.p) < -EPS;
      swap(sg.p, sg.q);
    }
  }
  return true;
}

graph makeGraph(vector<P> &pt, const vector<L> &road, const vector<L> &sign) {
  for (int i = 0; i < road.size(); i++) {
    pt.push_back(road[i].p);
    pt.push_back(road[i].q);
  }
  sort(pt.begin(), pt.end(), comp);
  pt.erase(unique(pt.begin(), pt.end()), pt.end());
  graph g(pt.size());
  for (int i = 0; i < road.size(); i++) {
    vector<pair<double, int>> vp;
    for (int j = 0; j < pt.size(); j++)
      if (spIntersect(road[i], pt[j]))
        vp.push_back(make_pair(abs(road[i].p - pt[j]), j));
    sort(vp.begin(), vp.end());
    for (int j = 0; j + 1 < vp.size(); j++) {
      int a = vp[j].second, b = vp[j + 1].second;
      if (checkSign(L(pt[a], pt[b]), sign))
        g[a].push_back(Node(b, abs(pt[a] - pt[b])));
      if (checkSign(L(pt[b], pt[a]), sign))
        g[b].push_back(Node(a, abs(pt[a] - pt[b])));
    }
  }
  return g;
}

void dijkstra(const graph &g, int s, int t, const vector<P> &vp) {
  int n = g.size();
  vector<bool> visit(n, false);
  vector<double> cost(n, 1e12);
  cost[s] = 0.0;
  vector<int> prev(n, -1);
  priority_queue<Node> qu;
  qu.push(Node(s, 0.0));
  while (!qu.empty()) {
    Node nd = qu.top();
    qu.pop();
    int pos = nd.pos;
    if (visit[pos])
      continue;
    if (pos == t) {
      vector<int> path;
      for (int p = t; p != -1; p = prev[p])
        path.push_back(p);
      reverse(path.begin(), path.end());
      for (int i = 0; i < path.size(); i++)
        printf("%d %d\\n", int(real(vp[path[i]]) + EPS),
               int(imag(vp[path[i]]) + EPS));
      puts("0");
      return;
    }
    for (int i = 0; i < g[pos].size(); i++) {
      int next = g[pos][i].pos;
      if (cost[pos] + g[pos][i].cost < cost[next]) {
        cost[next] = cost[pos] + g[pos][i].cost;
        prev[next] = pos;
        qu.push(Node(next, cost[next]));
      }
    }
  }
  puts("-1");
}

int main() {
  fstream cin("E.in");
  int n;
  while (cin >> n, n) {
    int xs, ys, xg, yg;
    cin >> xs >> ys >> xg >> yg;
    int x1, y1, x2, y2;
    vector<L> vl, road, sign;
    for (int i = 0; i < n; i++) {
      cin >> x1 >> y1 >> x2 >> y2;
      vl.push_back(L(P(x1, y1), P(x2, y2)));
    }
    for (int i = 0; i < n; i++) {
      bool bp = false, bq = false;
      for (int j = 0; j < n; j++) {
        if (i == j)
          continue;
        if (spIntersect(vl[j], vl[i].p))
          bp = true;
        if (spIntersect(vl[j], vl[i].q))
          bq = true;
      }
      if (bp & bq)
        road.push_back(vl[i]);
      else
        sign.push_back(vl[i]);
    }
    vector<P> vp;
    graph g = makeGraph(vp, road, sign);
    int sidx, gidx;
    for (int i = 0; i < vp.size(); i++) {
      if (abs(P(xs, ys) - vp[i]) < EPS)
        sidx = i;
      if (abs(P(xg, yg) - vp[i]) < EPS)
        gidx = i;
    }
    dijkstra(g, sidx, gidx, vp);
  }
}