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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
using ld = long double;
using P = complex<ld>;
using Pd = pair<ld, ld>;
using G = vector<P>;
const ld pi = acos(-1);
const ld eps = 1e-10;
const ld inf = 1e12;
typedef vector<P> region;

ld cross(const P &a, const P &b) {
  return a.real() * b.imag() - a.imag() * b.real();
}
ld dot(const P &a, const P &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
enum { CCW = +1, CW = -1, BEHIND = +2, FRONT = -2, ON = 0 };
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > eps)
    return CCW; // counter clockwise
  if (cross(b, c) < -eps)
    return CW; // clockwise
  if (dot(b, c) < 0)
    return BEHIND; // c--a--b on line
  if (norm(b) < norm(c))
    return FRONT; // a--b--c on line
  return ON;
}

struct L : public vector<P> {
  L(const P &a = 0, const P &b = 0) {
    push_back(a);
    push_back(b);
  }
  L(ld A, ld B, ld C) { // Ax + By + C = 0
    if (A < eps)
      *this = L(P(0, -C / B), P(1, -C / B));
    else if (B < eps)
      *this = L(P(-C / A, 0), P(-C / A, 1));
    *this = L(P(0, -C / B), P(-C / A, 0));
  }
  int ccw(const P &p) { return ::ccw((*this)[0], (*this)[1], p); }
};

P projection(const L &l, const P &p) {
  ld t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}
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
}
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;
}
ld distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r))
    return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
ld distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t))
    return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

int n, C;

bool adjacent(region r1, region r2) {
  int n1 = r1.size(), n2 = r2.size();
  for (int i = 0; i < r1.size(); i++) {
    for (int j = 0; j < r2.size(); j++) {
      P p11 = r1[i], p12 = r1[(i + 1) % n1];
      P p21 = r2[j], p22 = r2[(j + 1) % n2];
      if (p11.real() > p12.real())
        swap(p11, p12);
      if (p21.real() > p22.real())
        swap(p21, p22);
      L s1 = L(p11, p12), s2 = L(p21, p22);
      if (abs(cross(p11 - p12, p21 - p22)) > eps)
        continue;
      if (distanceSS(s1, s2) > eps)
        continue;
      vector<pair<Pd, int>> v;
      v.emplace_back(Pd(p11.real(), p11.imag()), 0);
      v.emplace_back(Pd(p12.real(), p12.imag()), 0);
      v.emplace_back(Pd(p21.real(), p21.imag()), 1);
      v.emplace_back(Pd(p22.real(), p22.imag()), 1);
      sort(v.begin(), v.end());
      if (v[1].first != v[2].first) {
        return true;
      }
    }
  }
  return false;
}

int adj[100][100];
int use[100];
int color[100];
int color_num;
int ans;

bool check() {
  for (int i = 0; i < C; i++) {
    for (int j = i + 1; j < C; j++) {
      if (adj[i][j] && color[i] == color[j])
        return false;
    }
  }
  return true;
}

void dfs(int n) {
  if (n == C) {
    if (check()) {
      ans = min(ans, color_num);
    }
    return;
  }
  for (int c = 0; c < C; c++) {
    bool ok = true;
    for (int i = 0; i < n; i++) {
      if (adj[n][i] && c == color[i]) {
        ok = false;
        break;
      }
    }
    if (ok) {
      use[c]++;
      if (use[c] == 1)
        color_num++;
      if (color_num < ans) {
        color[n] = c;
        dfs(n + 1);
      }
      use[c]--;
      if (use[c] == 0)
        color_num--;
    }
  }
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  while (cin >> n, n) {
    map<string, int> id;
    vector<string> name(n);
    vector<region> rs(n);
    for (int i = 0; i < n; i++) {
      cin >> name[i];
      id[name[i]] = -1;
      region r;
      int a, b;
      while (cin >> a, a != -1) {
        cin >> b;
        r.push_back(P(a, b));
      }
      rs[i] = r;
    }

    C = 0;
    for (auto &p : id) {
      id[p.first] = C++;
    }

    memset(adj, 0, sizeof adj);
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        int id1 = id[name[i]], id2 = id[name[j]];
        if (id1 == id2 || adj[id1][id2])
          continue;
        if (adjacent(rs[i], rs[j])) {
          adj[id1][id2] = adj[id2][id1] = 1;
        }
      }
    }

    use[0] = 1;
    color_num = 1;
    ans = 1000000;
    dfs(1);

    cout << ans << endl;
  }
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
using ld = long double;
using P = complex<ld>;
using Pd = pair<ld, ld>;
using G = vector<P>;
const ld pi = acos(-1);
const ld eps = 1e-10;
const ld inf = 1e12;
typedef vector<P> region;

ld cross(const P &a, const P &b) {
  return a.real() * b.imag() - a.imag() * b.real();
}
ld dot(const P &a, const P &b) {
  return a.real() * b.real() + a.imag() * b.imag();
}
enum { CCW = +1, CW = -1, BEHIND = +2, FRONT = -2, ON = 0 };
int ccw(P a, P b, P c) {
  b -= a;
  c -= a;
  if (cross(b, c) > eps)
    return CCW; // counter clockwise
  if (cross(b, c) < -eps)
    return CW; // clockwise
  if (dot(b, c) < 0)
    return BEHIND; // c--a--b on line
  if (norm(b) < norm(c))
    return FRONT; // a--b--c on line
  return ON;
}

struct L : public vector<P> {
  L(const P &a = 0, const P &b = 0) {
    push_back(a);
    push_back(b);
  }
  L(ld A, ld B, ld C) { // Ax + By + C = 0
    if (A < eps)
      *this = L(P(0, -C / B), P(1, -C / B));
    else if (B < eps)
      *this = L(P(-C / A, 0), P(-C / A, 1));
    *this = L(P(0, -C / B), P(-C / A, 0));
  }
  int ccw(const P &p) { return ::ccw((*this)[0], (*this)[1], p); }
};

P projection(const L &l, const P &p) {
  ld t = dot(p - l[0], l[0] - l[1]) / norm(l[0] - l[1]);
  return l[0] + t * (l[0] - l[1]);
}
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
}
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;
}
ld distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r))
    return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
ld distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t))
    return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

int n, C;

bool adjacent(region r1, region r2) {
  int n1 = r1.size(), n2 = r2.size();
  for (int i = 0; i < r1.size(); i++) {
    for (int j = 0; j < r2.size(); j++) {
      P p11 = r1[i], p12 = r1[(i + 1) % n1];
      P p21 = r2[j], p22 = r2[(j + 1) % n2];
      if (p11.real() > p12.real())
        swap(p11, p12);
      if (p21.real() > p22.real())
        swap(p21, p22);
      L s1 = L(p11, p12), s2 = L(p21, p22);
      if (abs(cross(p11 - p12, p21 - p22)) > eps)
        continue;
      if (distanceSS(s1, s2) > eps)
        continue;
      vector<pair<Pd, int>> v;
      v.emplace_back(Pd(p11.real(), p11.imag()), 0);
      v.emplace_back(Pd(p12.real(), p12.imag()), 0);
      v.emplace_back(Pd(p21.real(), p21.imag()), 1);
      v.emplace_back(Pd(p22.real(), p22.imag()), 1);
      sort(v.begin(), v.end());
      if (v[1].first != v[2].first) {
        return true;
      }
    }
  }
  return false;
}

int adj[100][100];
int color[100];
int ans;

bool check() {
  for (int i = 0; i < C; i++) {
    for (int j = i + 1; j < C; j++) {
      if (adj[i][j] && color[i] == color[j])
        return false;
    }
  }
  return true;
}

void dfs(int n) {
  if (n == C) {
    if (check()) {
      int cnt = 0;
      int used[100] = {0};
      for (int i = 0; i < C; i++) {
        if (!used[color[i]]) {
          used[color[i]] = true;
          cnt++;
        }
      }
      ans = min(ans, cnt);
    }
    return;
  }
  for (int c = 0; c < C; c++) {
    bool ok = true;
    for (int i = 0; i < n; i++) {
      if (adj[n][i] && c == color[i]) {
        ok = false;
        break;
      }
    }
    if (ok) {
      color[n] = c;
      dfs(n + 1);
    }
  }
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  while (cin >> n, n) {
    map<string, int> id;
    vector<string> name(n);
    vector<region> rs(n);
    for (int i = 0; i < n; i++) {
      cin >> name[i];
      id[name[i]] = -1;
      region r;
      int a, b;
      while (cin >> a, a != -1) {
        cin >> b;
        r.push_back(P(a, b));
      }
      rs[i] = r;
    }

    C = 0;
    for (auto &p : id) {
      id[p.first] = C++;
    }

    memset(adj, 0, sizeof adj);
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        int id1 = id[name[i]], id2 = id[name[j]];
        if (id1 == id2 || adj[id1][id2])
          continue;
        if (adjacent(rs[i], rs[j])) {
          adj[id1][id2] = adj[id2][id1] = 1;
        }
      }
    }

    ans = 1000000;
    dfs(1);

    cout << ans << endl;
  }
}