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

#include <bits/stdc++.h>

#define EQ(a, b) (abs((a) - (b)) < EPS)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define fs first
#define sc second
#define pb push_back
#define sz size()
#define all(a) (a).begin(), (a).end()

using namespace std;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef double D;
typedef complex<D> P;
typedef pair<P, P> L;

const D EPS = 1e-8;

inline D dot(P x, P y) { return real(conj(x) * y); }
inline D cross(P x, P y) { return imag(conj(x) * y); }

inline int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // counter clockwise
  if (cross(b, c) < -EPS)
    return -1; // clockwise
  if (dot(b, c) < -EPS)
    return 2; // c--a--b on line
  if (abs(b) + EPS < abs(c))
    return -2; // a--b--c on line
  return 0;    // on segment
}

inline bool is_cp(L a, L b) {
  if (ccw(a.fs, a.sc, b.fs) * ccw(a.fs, a.sc, b.sc) <= 0)
    if (ccw(b.fs, b.sc, a.fs) * ccw(b.fs, b.sc, a.sc) <= 0)
      return true;
  return false;
}

class BiMatch {
  int n;
  vector<vi> g;
  vi match, use;

public:
  BiMatch(int v) : n(v), g(n, vi()) {}

  void AddEdge(int u, int v) {
    g[u].pb(v);
    g[v].pb(u);
  }

  bool dfs(int v) {
    use[v] = 1;
    for (int u : g[v]) {
      int w = match[u];
      if (w < 0 || (!use[w] && dfs(w))) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }

  int matching() {
    int res = 0;
    match = vi(n, -1);
    rep(v, n) {
      if (match[v] < 0) {
        use = vi(n, 0);
        if (dfs(v))
          res++;
      }
    }
    return res;
  }
};

const int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1},
          dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int sy[] = {0, 1, 1, 0}, sx[] = {1, 1, 0, 0};
int main() {
  int h, w;
  while (cin >> h >> w, h) {
    vector<string> s(h);
    rep(i, h) cin >> s[i];

    int corner = 0;
    vector<vi> tate(h + 1), yoko(w + 1);
    vector<vector<L>> lt(h + 1), ly(w + 1);

    rep(y, h) rep(x, w) {
      if (s[y][x] == '.') {
        rep(d, 4) {
          bool f = true;
          rep(j, 3) {
            int ny = y + dy[(2 * d + j) % 8], nx = x + dx[(2 * d + j) % 8];
            if (ny < 0 || nx < 0 || ny >= h || nx >= w)
              f = false;
            else if (s[ny][nx] == '.')
              f = false;
          }
          if (f) {
            corner++;
            tate[y + sy[d]].push_back(x + sx[d]);
            yoko[x + sx[d]].push_back(y + sy[d]);
          }
        }
      } else {
        rep(d, 4) {
          int ny = y + dy[2 * d], nx = x + dx[2 * d];
          if (ny < 0 || nx < 0 || ny >= h || nx >= w || s[ny][nx] == '.') {
            L wall = make_pair(P(x + sx[(d + 3) % 4], y + sy[(d + 3) % 4]),
                               P(x + sx[d], y + sy[d]));
            lt[y + sy[(d + 3) % 4]].push_back(wall);
            lt[y + sy[d]].push_back(wall);
            ly[x + sx[(d + 3) % 4]].push_back(wall);
            ly[x + sx[d]].push_back(wall);
          }
        }
      }
    }

    rep(i, h + 1) sort(all(tate[i]));
    rep(i, w + 1) sort(all(yoko[i]));

    vector<L> segs;
    rep(y, h + 1) rep(i, tate[y].size() - 1) {
      L a = L(P(tate[y][i], y), P(tate[y][i + 1], y));
      bool f = true;
      for (L b : lt[y]) {
        if (EQ(a.fs, b.fs) || EQ(a.sc, b.fs)) {
          if (ccw(a.fs, a.sc, b.sc) == 0) {
            f = false;
            break;
          } else
            continue;
        }
        if (EQ(a.fs, b.sc) || EQ(a.sc, b.sc)) {
          if (ccw(a.fs, a.sc, b.fs) == 0) {
            f = false;
            break;
          } else
            continue;
        }
        if (is_cp(a, b)) {
          f = false;
          break;
        }
      }
      if (f)
        segs.pb(a);
    }

    rep(x, w + 1) rep(i, yoko[x].size() - 1) {
      L a = L(P(x, yoko[x][i]), P(x, yoko[x][i + 1]));
      bool f = true;
      for (L b : ly[x]) {
        if (EQ(a.fs, b.fs) || EQ(a.sc, b.fs)) {
          if (ccw(a.fs, a.sc, b.sc) == 0) {
            f = false;
            break;
          } else
            continue;
        }
        if (EQ(a.fs, b.sc) || EQ(a.sc, b.sc)) {
          if (ccw(a.fs, a.sc, b.fs) == 0) {
            f = false;
            break;
          } else
            continue;
        }
        if (is_cp(a, b)) {
          f = false;
          break;
        }
      }
      if (f)
        segs.pb(a);
    }

    BiMatch bim(segs.size());
    rep(i, segs.size()) rep(j, i) {
      if (is_cp(segs[i], segs[j]))
        bim.AddEdge(i, j);
    }
    cout << corner - (segs.size() - bim.matching()) + 1 << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define EQ(a, b) (abs((a) - (b)) < EPS)
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define fs first
#define sc second
#define pb push_back
#define sz size()
#define all(a) (a).begin(), (a).end()

using namespace std;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef double D;
typedef complex<D> P;
typedef pair<P, P> L;

const D EPS = 1e-8;

inline D dot(P x, P y) { return real(conj(x) * y); }
inline D cross(P x, P y) { return imag(conj(x) * y); }

int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // counter clockwise
  if (cross(b, c) < -EPS)
    return -1; // clockwise
  if (dot(b, c) < -EPS)
    return 2; // c--a--b on line
  if (abs(b) + EPS < abs(c))
    return -2; // a--b--c on line
  return 0;    // on segment
}

inline bool is_cp(L a, L b) {
  if (ccw(a.fs, a.sc, b.fs) * ccw(a.fs, a.sc, b.sc) <= 0)
    if (ccw(b.fs, b.sc, a.fs) * ccw(b.fs, b.sc, a.sc) <= 0)
      return true;
  return false;
}

class BiMatch {
  int n;
  vector<vi> g;
  vi match, use;

public:
  BiMatch(int v) : n(v), g(n, vi()) {}

  void AddEdge(int u, int v) {
    g[u].pb(v);
    g[v].pb(u);
  }

  bool dfs(int v) {
    use[v] = 1;
    for (int u : g[v]) {
      int w = match[u];
      if (w < 0 || (!use[w] && dfs(w))) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }

  int matching() {
    int res = 0;
    match = vi(n, -1);
    rep(v, n) {
      if (match[v] < 0) {
        use = vi(n, 0);
        if (dfs(v))
          res++;
      }
    }
    return res;
  }
};

const int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1},
          dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
const int sy[] = {0, 1, 1, 0}, sx[] = {1, 1, 0, 0};
int main() {
  int h, w;
  while (cin >> h >> w, h) {
    vector<string> s(h);
    rep(i, h) cin >> s[i];

    int corner = 0;
    vector<P> v;
    vector<L> l;
    rep(y, h) rep(x, w) {
      if (s[y][x] == '.') {
        rep(d, 4) {
          bool f = true;
          rep(j, 3) {
            int ny = y + dy[(2 * d + j) % 8], nx = x + dx[(2 * d + j) % 8];
            if (ny < 0 || nx < 0 || ny >= h || nx >= w)
              f = false;
            else if (s[ny][nx] == '.')
              f = false;
          }
          if (f) {
            corner++;
            v.pb(P(x + sx[d], y + sy[d]));
          }
        }
      } else {
        rep(d, 4) {
          int ny = y + dy[2 * d], nx = x + dx[2 * d];
          if (ny < 0 || nx < 0 || ny >= h || nx >= w || s[ny][nx] == '.') {
            l.push_back(make_pair(P(x + sx[(d + 3) % 4], y + sy[(d + 3) % 4]),
                                  P(x + sx[d], y + sy[d])));
          }
        }
      }
    }

    /*
    rep(i,v.size())cout << v[i].fs << " " << v[i].sc << endl;
    rep(i,l.size())cout << l[i].fs.fs << " " << l[i].fs.sc << " " << l[i].sc.fs
    << " " << l[i].sc.sc << endl;
    */

    vector<L> segs;
    rep(i, v.size()) rep(j, i) {
      if (EQ(v[i].real(), v[j].real()) || EQ(v[i].imag(), v[j].imag())) {
        L seg = L(v[i], v[j]);
        bool f = true;
        rep(k, l.size()) {
          if (EQ(l[k].fs, v[i]) || EQ(l[k].fs, v[j])) {
            if (ccw(v[i], v[j], l[k].sc) == 0) {
              f = false;
              break;
            } else
              continue;
          }
          if (EQ(l[k].sc, v[i]) || EQ(l[k].sc, v[j])) {
            if (ccw(v[i], v[j], l[k].fs) == 0) {
              f = false;
              break;
            } else
              continue;
          }
          if (is_cp(seg, l[k])) {
            f = false;
            break;
          }
        }
        if (f)
          segs.pb(seg);
      }
    }

    BiMatch bim(segs.size());
    rep(i, segs.size()) rep(j, i) {
      if (is_cp(segs[i], segs[j]))
        bim.AddEdge(i, j);
    }
    cout << v.size() - (segs.size() - bim.matching()) + 1 << endl;
  }
}