Problem p00833 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/

typedef long double ld;
const ld PI = acos(-1.0);
bool eq(ld a, ld b) { return abs(a - b) < EPS; }
typedef complex<ld> Point;
typedef vector<Point> Polygon;

namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

struct Line {
  Point a, b;
  Line(Point p, Point q) : a(p), b(q){};
  Line(ld x1, ld y1, ld x2, ld y2) : a(Point(x1, y1)), b(Point(x2, y2)){};
};

struct Circle {
  Point p;
  ld r;
  Circle(Point a, ld b) : p(a), r(b){};
};

ld dot(Point a, Point b) { return real(conj(a) * b); }

ld cross(Point a, Point b) { return imag(conj(a) * b); }

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // counter cloclwise
  if (cross(b, c) < -EPS)
    return -1; // cloclwise
  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;    // a--c--b on line
}

bool isis_ll(Line l, Line m) { return abs(cross(l.b - l.a, m.b - m.a)) > EPS; }

bool isis_sp(Line s, Point p) {
  if (s.a == p || s.b == p)
    return false;
  return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a)) < EPS;
}

bool is_cover(Line s, Line t) {
  if (isis_ll(s, t))
    return false;
  if ((s.a == t.a && s.b == t.b) || (s.a == t.b && t.a == s.b))
    return true;
  int cnt = 0;
  if (isis_sp(s, t.a))
    cnt++;
  if (isis_sp(s, t.b))
    cnt++;
  if (isis_sp(t, s.a))
    cnt++;
  if (isis_sp(t, s.b))
    cnt++;
  return cnt > 0;
}

typedef int Weight;
struct Edge {
  int from, to;
  Weight cost;
  bool operator<(const Edge &e) const { return cost < e.cost; }
  bool operator>(const Edge &e) const { return cost > e.cost; }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
void add_edge(Graph &g, int from, int to, Weight cost) {
  g[from].push_back(Edge{from, to, cost});
}

int ans;
int cnt;
Matrix g;
vi belong;

void solve(int bit, int col) {
  if (bit == (1 << cnt) - 1) {
    chmin(ans, col);
    return;
  }
  if (col == ans)
    return;
  vi white;
  REP(i, cnt) {
    if (!((bit >> i) & 1)) {
      white.push_back(i);
    }
  }
  REP(i, 1 << white.size()) {
    vi use;
    REP(j, white.size()) {
      if ((i >> j) & 1)
        use.push_back(white[j]);
    }
    bool f = false;
    REP(j, use.size()) REP(k, j) {
      if (g[use[j]][use[k]])
        f = true;
    }
    if (f)
      continue;
    int nx = bit;
    REP(j, use.size()) nx |= 1 << use[j];
    solve(nx, col + 1);
  }
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  int n;
  while (cin >> n, n) {
    belong.clear();
    g.clear();
    belong.resize(n);
    ans = 10;
    cnt = 0;
    vector<Polygon> ps(n);
    map<string, int> mp;
    REP(i, n) {
      string s;
      cin >> s;
      if (!mp.count(s)) {
        mp[s] = cnt;
        cnt++;
      }
      belong[i] = mp[s];
      int a, b;
      while (cin >> a, a >= 0) {
        cin >> b;
        ps[i].emplace_back(a, b);
      }
    }
    g.resize(cnt, Array(cnt));
    REP(i, n) REP(j, i) {
      if (belong[i] == belong[j])
        continue;
      bool f = false;
      REP(k, ps[i].size()) REP(l, ps[j].size()) {
        Line s1(ps[i][k], ps[i][(k + 1) % ps[i].size()]),
            s2(ps[j][l], ps[j][(l + 1) % ps[j].size()]);
        if (is_cover(s1, s2))
          f = true;
      }
      if (f) {
        g[belong[j]][belong[i]] = 1;
        g[belong[i]][belong[j]] = 1;
      }
    }
    solve(0, 0);
    cout << ans << endl;
  }
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define FOR(i, k, n) for (int i = (int)(k); i < (int)(n); i++)
#define REP(i, n) FOR(i, 0, n)
#define ALL(a) a.begin(), a.end()
#define MS(m, v) memset(m, v, sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template <class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/

typedef long double ld;
const ld PI = acos(-1.0);
bool eq(ld a, ld b) { return abs(a - b) < EPS; }
typedef complex<ld> Point;
typedef vector<Point> Polygon;

namespace std {
bool operator<(const Point &a, const Point &b) {
  return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
}
} // namespace std

struct Line {
  Point a, b;
  Line(Point p, Point q) : a(p), b(q){};
  Line(ld x1, ld y1, ld x2, ld y2) : a(Point(x1, y1)), b(Point(x2, y2)){};
};

struct Circle {
  Point p;
  ld r;
  Circle(Point a, ld b) : p(a), r(b){};
};

ld dot(Point a, Point b) { return real(conj(a) * b); }

ld cross(Point a, Point b) { return imag(conj(a) * b); }

int ccw(Point a, Point b, Point c) {
  b -= a;
  c -= a;
  if (cross(b, c) > EPS)
    return 1; // counter cloclwise
  if (cross(b, c) < -EPS)
    return -1; // cloclwise
  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;    // a--c--b on line
}

bool isis_ll(Line l, Line m) { return abs(cross(l.b - l.a, m.b - m.a)) > EPS; }

bool isis_sp(Line s, Point p) {
  if (s.a == p || s.b == p)
    return false;
  return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a)) < EPS;
}

bool is_cover(Line s, Line t) {
  if (isis_ll(s, t))
    return false;
  if ((s.a == t.a && s.b == t.b) || (s.a == t.b && t.a == s.b))
    return true;
  int cnt = 0;
  if (isis_sp(s, t.a))
    cnt++;
  if (isis_sp(s, t.b))
    cnt++;
  if (isis_sp(t, s.a))
    cnt++;
  if (isis_sp(t, s.b))
    cnt++;
  return cnt > 0;
}

typedef int Weight;
struct Edge {
  int from, to;
  Weight cost;
  bool operator<(const Edge &e) const { return cost < e.cost; }
  bool operator>(const Edge &e) const { return cost > e.cost; }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
void add_edge(Graph &g, int from, int to, Weight cost) {
  g[from].push_back(Edge{from, to, cost});
}

int ans;
int cnt;
Matrix g;
vi belong;

void solve(int bit, int col) {
  if (bit == (1 << cnt) - 1) {
    chmin(ans, col);
    return;
  }
  if (col == ans)
    return;
  vi white;
  REP(i, cnt) {
    if (!((bit >> i) & 1)) {
      white.push_back(i);
    }
  }
  REP(i, 1 << white.size()) {
    if (!i & 1)
      continue;
    vi use;
    REP(j, white.size()) {
      if ((i >> j) & 1)
        use.push_back(white[j]);
    }
    bool f = false;
    REP(j, use.size()) REP(k, j) {
      if (g[use[j]][use[k]])
        f = true;
    }
    if (f)
      continue;
    int nx = bit;
    REP(j, use.size()) nx |= 1 << use[j];
    solve(nx, col + 1);
  }
}

int main() {
  cin.sync_with_stdio(false);
  cout << fixed << setprecision(10);
  int n;
  while (cin >> n, n) {
    belong.clear();
    g.clear();
    belong.resize(n);
    ans = 10;
    cnt = 0;
    vector<Polygon> ps(n);
    map<string, int> mp;
    REP(i, n) {
      string s;
      cin >> s;
      if (!mp.count(s)) {
        mp[s] = cnt;
        cnt++;
      }
      belong[i] = mp[s];
      int a, b;
      while (cin >> a, a >= 0) {
        cin >> b;
        ps[i].emplace_back(a, b);
      }
    }
    g.resize(cnt, Array(cnt));
    REP(i, n) REP(j, i) {
      if (belong[i] == belong[j])
        continue;
      bool f = false;
      REP(k, ps[i].size()) REP(l, ps[j].size()) {
        Line s1(ps[i][k], ps[i][(k + 1) % ps[i].size()]),
            s2(ps[j][l], ps[j][(l + 1) % ps[j].size()]);
        if (is_cover(s1, s2))
          f = true;
      }
      if (f) {
        g[belong[j]][belong[i]] = 1;
        g[belong[i]][belong[j]] = 1;
      }
    }
    solve(0, 0);
    cout << ans << endl;
  }
  return 0;
}