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

#include <bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1 << 30
#define eps (1e-11)
#define MAX 700
#define equals(a, b) (fabs((a) - (b)) < eps)
using namespace std;

class Point {
public:
  double x, y;
  Point(double x = 0, double y = 0) : x(x), y(y) {}

  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double k) { return Point(x * k, y * k); }
  Point operator/(double k) { return Point(x / k, y / k); }
  bool operator<(Point p) const { return (x != p.x ? x < p.x : y < p.y); }
  bool operator==(Point p) const {
    return fabs(x - p.x) < eps && fabs(y - p.y) < eps;
  }

  double abs() { return sqrt(norm()); }
  double norm() { return (x * x + y * y); }
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment {
public:
  Point p1, p2;
  Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
};
typedef Segment Line;

double norm(Vector a) { return (a.x * a.x + a.y * a.y); }
double abs(Vector a) { return sqrt(norm(a)); }
double dot(Vector a, Vector b) { return (a.x * b.x + a.y * b.y); }
double cross(Vector a, Vector b) { return (a.x * b.y - a.y * b.x); }

struct edge {
  int to, cap;
  double cost;
  int rev;
};

int v;
vector<edge> e[MAX];
double h[MAX];
double dist[MAX];
int prevv[MAX], preve[MAX];

void add_edge(int from, int to, int cap, double cost) {
  e[from].push_back((edge){to, cap, cost, (int)e[to].size()});
  e[to].push_back((edge){from, 0, -cost, (int)e[from].size() - 1});
}

typedef pair<int, double> P;

double min_cost_flow(int s, int t, int f) {
  double res = 0.0;
  fill(h, h + v, 0);
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P>> pq;
    fill(dist, dist + v, inf);
    dist[s] = 0;
    pq.push(P(0, s));
    while (pq.size()) {
      P p = pq.top();
      pq.pop();
      int u = p.second;
      if (dist[u] - p.first < -eps)
        continue;
      for (int i = 0; i < e[u].size(); i++) {
        edge &E = e[u][i];
        if (E.cap > 0 &&
            (dist[u] + E.cost + h[u] - h[E.to]) - dist[E.to] < -eps) {
          dist[E.to] = dist[u] + E.cost + h[u] - h[E.to];
          prevv[E.to] = u;
          preve[E.to] = i;
          pq.push(P(dist[E.to], E.to));
        }
      }
    }
    if (dist[t] == inf)
      return -1;
    for (int i = 0; i < v; i++)
      h[i] += dist[i];

    int d = f;
    for (int u = t; u != s; u = prevv[u]) {
      d = min(d, e[prevv[u]][preve[u]].cap);
    }
    f -= d;
    res += (double)d * h[t];
    for (int u = t; u != s; u = prevv[u]) {
      edge &E = e[prevv[u]][preve[u]];
      E.cap -= d;
      e[u][E.rev].cap += d;
    }
  }
  return res;
}

int main() {
  int n;
  vector<Segment> vs, vt;
  Point st;
  double ans = 0.0;

  cin >> n;
  cin >> st.x >> st.y;
  for (int i = 0; i < n; i++) {
    Point a, b;
    cin >> a.x >> a.y >> b.x >> b.y;
    Segment s(a, b);
    vt.push_back(Segment(a, b));
    ans += abs(b - a);
  }

  int s = vt.size() * 2;
  int t = s + 1;
  v = t + 1;
  for (int i = 0; i < vt.size(); i++) {
    for (int j = 0; j < vt.size(); j++) {
      add_edge(i, j + vt.size(), 1, abs(vt[i].p2 - vt[j].p1));
    }
  }
  for (int i = 0; i < vt.size(); i++) {
    add_edge(s, i, 1, 0);
    add_edge(i + vt.size(), t, 1, 0);
  }
  printf("%.10f\\n", ans + min_cost_flow(s, t, vt.size()));
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
#define f first
#define s second
#define mp make_pair
#define pi M_PI
#define inf 1 << 30
#define eps (1e-11)
#define MAX 100000
#define equals(a, b) (fabs((a) - (b)) < eps)
using namespace std;

class Point {
public:
  double x, y;
  Point(double x = 0, double y = 0) : x(x), y(y) {}

  Point operator+(Point p) { return Point(x + p.x, y + p.y); }
  Point operator-(Point p) { return Point(x - p.x, y - p.y); }
  Point operator*(double k) { return Point(x * k, y * k); }
  Point operator/(double k) { return Point(x / k, y / k); }
  bool operator<(Point p) const { return (x != p.x ? x < p.x : y < p.y); }
  bool operator==(Point p) const {
    return fabs(x - p.x) < eps && fabs(y - p.y) < eps;
  }

  double abs() { return sqrt(norm()); }
  double norm() { return (x * x + y * y); }
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment {
public:
  Point p1, p2;
  Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
};
typedef Segment Line;

double norm(Vector a) { return (a.x * a.x + a.y * a.y); }
double abs(Vector a) { return sqrt(norm(a)); }
double dot(Vector a, Vector b) { return (a.x * b.x + a.y * b.y); }
double cross(Vector a, Vector b) { return (a.x * b.y - a.y * b.x); }

int ccw(Point p0, Point p1, Point p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (cross(a, b) > eps)
    return 1;
  if (cross(a, b) < -eps)
    return -1;
  if (dot(a, b) < -eps)
    return 2;
  if (a.norm() < b.norm())
    return -2;
  return 0;
}

bool intersect(Point p1, Point p2, Point p3, Point p4) {
  return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
          ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}

bool intersect(Segment s1, Segment s2) {
  return intersect(s1.p1, s1.p2, s2.p1, s2.p2);
}

Point getCrossPointLL(Line a, Line b) {
  double A = cross(a.p2 - a.p1, b.p2 - b.p1);
  double B = cross(a.p2 - a.p1, a.p2 - b.p1);
  if (abs(A) < eps || abs(B) < eps)
    return b.p1;
  return b.p1 + (b.p2 - b.p1) * (B / A);
}

struct edge {
  int to, cap;
  double cost;
  int rev;
};

int v;
vector<edge> e[MAX];
double h[MAX];
double dist[MAX];
int prevv[MAX], preve[MAX];

void add_edge(int from, int to, int cap, double cost) {
  e[from].push_back((edge){to, cap, cost, (int)e[to].size()});
  e[to].push_back((edge){from, 0, -cost, (int)e[from].size() - 1});
}

typedef pair<int, double> P;

double min_cost_flow(int s, int t, int f) {
  double res = 0.0;
  fill(h, h + v, 0);
  while (f > 0) {
    priority_queue<P, vector<P>, greater<P>> pq;
    fill(dist, dist + v, inf);
    dist[s] = 0;
    pq.push(P(0, s));
    while (pq.size()) {
      P p = pq.top();
      pq.pop();
      int u = p.second;
      if (dist[u] - p.first < -eps)
        continue;
      for (int i = 0; i < e[u].size(); i++) {
        edge &E = e[u][i];
        if (E.cap > 0 &&
            (dist[u] + E.cost + h[u] - h[E.to]) - dist[E.to] < -eps) {
          dist[E.to] = dist[u] + E.cost + h[u] - h[E.to];
          prevv[E.to] = u;
          preve[E.to] = i;
          pq.push(P(dist[E.to], E.to));
        }
      }
    }
    if (dist[t] == inf)
      return -1;
    for (int i = 0; i < v; i++)
      h[i] += dist[i];

    int d = f;
    for (int u = t; u != s; u = prevv[u]) {
      d = min(d, e[prevv[u]][preve[u]].cap);
    }
    f -= d;
    res += (double)d * h[t];
    for (int u = t; u != s; u = prevv[u]) {
      edge &E = e[prevv[u]][preve[u]];
      E.cap -= d;
      e[u][E.rev].cap += d;
    }
  }
  return res;
}

int main() {
  int n;
  vector<Segment> vs, vt;
  vector<Point> ps;
  Point st;
  double ans = 0.0;

  cin >> n;
  cin >> st.x >> st.y;
  for (int i = 0; i < n; i++) {
    Point a, b;
    cin >> a.x >> a.y >> b.x >> b.y;
    Segment s(a, b);
    if (ccw(a, b, st) == 0) {
      vs.push_back(Segment(a, st));
      vs.push_back(Segment(st, b));
    } else
      vs.push_back(Segment(a, b));
    ans += abs(b - a);
  }

  for (int i = 0; i < vs.size(); i++) {
    ps.push_back(vs[i].p1);
    ps.push_back(vs[i].p2);
    for (int j = i + 1; j < vs.size(); j++) {
      if (intersect(vs[i], vs[j]))
        ps.push_back(getCrossPointLL(vs[i], vs[j]));
    }
  }
  sort(ps.begin(), ps.end());
  ps.erase(unique(ps.begin(), ps.end()), ps.end());
  for (int i = 0; i < vs.size(); i++) {
    vector<pair<double, int>> list;
    for (int j = 0; j < ps.size(); j++)
      if (ccw(vs[i].p1, vs[i].p2, ps[j]) == 0)
        list.push_back(mp(norm(vs[i].p1 - ps[j]), j));
    sort(list.begin(), list.end());
    for (int j = 0; j < list.size() - 1; j++) {
      int a = list[j].s, b = list[j + 1].s;
      vt.push_back(Segment(ps[a], ps[b]));
    }
  }

  int s = vt.size() * 2;
  int t = s + 1;
  v = t + 1;
  for (int i = 0; i < vt.size(); i++) {
    for (int j = 0; j < vt.size(); j++) {
      if (i == j)
        continue;
      add_edge(i, j + vt.size(), 1, abs(vt[i].p2 - vt[j].p1));
    }
  }
  for (int i = 0; i < vt.size(); i++) {
    add_edge(s, i, 1, 0);
    add_edge(i + vt.size(), t, 1, 0);
  }
  printf("%.10f\\n", ans + min_cost_flow(s, t, vt.size()));
  return 0;
}