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

#include <bits/stdc++.h>
using namespace std;

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

int Signum(double x) { return x < -EPS ? -1 : x > EPS ? 1 : 0; }

struct Point {
  double x, y;
  Point() {}
  Point(double x, double y) : x(x), y(y) {}
  Point &operator+=(Point p) {
    x += p.x, y += p.y;
    return *this;
  }
  Point &operator-=(Point p) {
    x -= p.x, y -= p.y;
    return *this;
  }
  Point &operator*=(double c) {
    x *= c, y *= c;
    return *this;
  }
  Point &operator/=(double c) {
    x /= c, y /= c;
    return *this;
  }
};
Point operator+(Point a, Point b) { return a += b; }
Point operator-(Point a, Point b) { return a -= b; }
Point operator*(Point a, double c) { return a *= c; }
Point operator*(double c, Point a) { return a *= c; }
Point operator/(Point a, double c) { return a /= c; }
bool operator==(Point a, Point b) {
  return abs(a.x - b.x) < EPS && abs(a.y - b.y) < EPS;
}
bool operator!=(Point a, Point b) { return !(a == b); }

double Abs2(Point p) { return p.x * p.x + p.y * p.y; }
double Dot(Point a, Point b) { return a.x * b.x + a.y * b.y; }
double Cross(Point a, Point b) { return a.x * b.y - a.y * b.x; }

struct Segment {
  Point pos, dir;
  Segment() {}
  Segment(Point p, Point d) : pos(p), dir(d) {}
  Segment(double px, double py, double dx, double dy)
      : pos(px, py), dir(dx, dy) {}
  // explicit Segment(Line l):pos(l.pos),dir(l.dir){}
  // explicit operator Line()const{return Line(pos,dir);}
};

int CCW(Point a, Point b, Point c) {
  b -= a, c -= a;
  if (int sign = Signum(Cross(b, c)))
    return sign; // 1:ccw,-1:cw
  // if(Dot(b,c)<-EPS)
  //	return -2;   // c-a-b
  // if(Abs2(b)<Abs2(c)-EPS)
  //	return 2;    // a-b-c
  // return 0;        // a-c-b (inclusive)
  if (Dot(b, c) < EPS)
    return -2; // c-a-b
  if (Abs2(b) < Abs2(c) + EPS)
    return 2; // a-b-c
  return 0;   // a-c-b (exclusive)
}
bool IntersectSS(Segment a, Segment b) {
  int c1 = CCW(a.pos, a.pos + a.dir, b.pos),
      c2 = CCW(a.pos, a.pos + a.dir, b.pos + b.dir);
  int c3 = CCW(b.pos, b.pos + b.dir, a.pos),
      c4 = CCW(b.pos, b.pos + b.dir, a.pos + a.dir);
  return c1 * c2 <= 0 && c3 * c4 <= 0;
}

int solve(const vvi &g, int u, vi &color) {
  int n = g.size();
  if (u == n)
    return *max_element(all(color)) + 1;
  int mx = *max_element(all(color));
  int res = INF;
  for (int c = 0; c <= mx + 1; c++) {
    bool ok = true;
    for (int v : g[u])
      if (color[v] == c) {
        ok = false;
        break;
      }
    if (ok) {
      color[u] = c;
      res = min(res, solve(g, u + 1, color));
      color[u] = -1;
    }
  }
  return res;
}

int main() {
  for (int m; cin >> m && m;) {
    map<string, int> ntoi;
    vi is(m);
    vvi xs(m), ys(m);
    rep(i, m) {
      string name;
      cin >> name;
      ntoi.insert(mp(name, ntoi.size()));
      is[i] = ntoi[name];
      for (int x, y; cin >> x && x != -1;) {
        cin >> y;
        xs[i].push_back(x);
        ys[i].push_back(y);
      }
    }

    int n = ntoi.size();
    vvi g(n);
    rep(i, m) repi(j, i + 1, m) {
      int u = is[i], v = is[j];
      if (u == v)
        continue;
      rep(k, xs[i].size()) rep(l, xs[j].size()) {
        int x1, y1, x2, y2;
        x1 = xs[i][k], x2 = xs[i][(k + 1) % xs[i].size()];
        y1 = ys[i][k], y2 = ys[i][(k + 1) % ys[i].size()];
        Segment s1(x1, y1, x2 - x1, y2 - y1);
        x1 = xs[j][l], x2 = xs[j][(l + 1) % xs[j].size()];
        y1 = ys[j][l], y2 = ys[j][(l + 1) % ys[j].size()];
        Segment s2(x1, y1, x2 - x1, y2 - y1);
        if (IntersectSS(s1, s2)) {
          g[u].push_back(v);
          g[v].push_back(u);
          goto end;
        }
      }
    end:;
    }
    rep(i, n) {
      sort(all(g[i]));
      g[i].erase(unique(all(g[i])), end(g[i]));
    }

    vi color(n, -1);
    cout << solve(g, 0, color) << endl;
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define dump(n) cout << "# " << #n << '=' << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define all(c) begin(c), end(c)
#define mp make_pair
#define mt make_tuple

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << '(' << p.first << ',' << p.second << ')';
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &a) {
  os << '[';
  rep(i, a.size()) os << (i ? " " : "") << a[i];
  return os << ']';
}

int isccw(const vi &xs, const vi &ys) {
  int sum = 0;
  rep(i, xs.size()) {
    int x1 = xs[i], x2 = xs[(i + 1) % xs.size()];
    int y1 = ys[i], y2 = ys[(i + 1) % ys.size()];
    sum += x1 * y2 - y1 * x2;
  }
  assert(sum);
  return sum > 0;
}

int solve(const vvi &g, int u, vi &color) {
  int n = g.size();
  if (u == n)
    return *max_element(all(color)) + 1;
  int res = INF;
  for (int c = 0; c < n; c++) {
    bool ok = true;
    for (int v : g[u])
      if (color[v] == c) {
        ok = false;
        break;
      }
    if (ok) {
      color[u] = c;
      res = min(res, solve(g, u + 1, color));
      color[u] = -1;
    }
  }
  return res;
}

int main() {
  for (int n; cin >> n && n;) {
    map<string, int> ntoi;
    const int h = 1001, w = 1001;
    vvi grid(h, vi(w, -1));
    rep(_, n) {
      string name;
      cin >> name;
      ntoi.insert(mp(name, ntoi.size()));
      int v = ntoi[name];
      vi xs, ys;
      for (int x, y; cin >> x && x != -1;) {
        cin >> y;
        xs.push_back(x);
        ys.push_back(y);
      }
      if (!isccw(xs, ys)) {
        reverse(all(xs));
        reverse(all(ys));
      }
      rep(i, xs.size()) {
        int x1 = xs[i], x2 = xs[(i + 1) % xs.size()];
        int y1 = ys[i], y2 = ys[(i + 1) % ys.size()];
        if (x1 < x2 && y1 == y2)
          repi(x, x1, x2) grid[y1][x] = v;
        if (x1 > x2 && y1 == y2)
          peri(x, x2, x1) grid[y1 - 1][x] = v;
        if (x1 == x2 && y1 < y2)
          repi(y, y1, y2) grid[y][x1 - 1] = v;
        if (x1 == x2 && y1 > y2)
          peri(y, y2, y1) grid[y][x1] = v;
      }
    }

    n = ntoi.size();
    vvi d(n, vi(n));
    rep(i, h) rep(j, w) rep(k, 4) {
      int ni = i + "\\xff\\x1\\0\\0"[k], nj = j + "\\0\\0\\xff\\x1"[k];
      if (ni < 0 || h <= ni || nj < 0 || w <= nj)
        continue;
      int u = grid[i][j], v = grid[ni][nj];
      if (u != -1 && v != -1 && u != v)
        d[u][v] = d[v][u] = 1;
    }

    vvi g(n);
    rep(i, n) rep(j, n) if (d[i][j]) g[i].push_back(j);

    // rep(i,n) dump(g[i]);

    vi color(n, -1);
    cout << solve(g, 0, color) << endl;
  }
}