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

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

struct UnionFind {
private:
  std::vector<int> value;

public:
  UnionFind(int size) : value(size, -1) {}
  int find(int x) { return value[x] < 0 ? x : value[x] = find(value[x]); }
  int size(int x) { return -value[find(x)]; }
  bool same(int x, int y) { return find(x) == find(y); }
  bool unite(int x, int y) {
    if ((x = find(x)) == (y = find(y)))
      return false;
    if (value[x] > value[y])
      std::swap(x, y);
    value[x] += value[y];
    value[y] = x;
    return true;
  }
};

const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
const int T[] = {3, 5, 6, 9, 10, 12};

int h, w;
int c[9][9];
int can[9][9];
int need[9][9];
int ban[9][9];
int ch[9][9];

int pack(int x, int y) { return (x - 1) * w + (y - 1); }

bool check() {
  UnionFind uf(h * w);
  int last = -1;
  int cnt = 0;
  for (int pos = 0; pos < h * w; pos++) {
    int x = pos / w + 1;
    int y = pos % w + 1;
    if (c[x][y])
      continue;
    last = pos;
    cnt++;
    for (int i = 0; i < 4; i++) {
      int nx = x + dx[i];
      int ny = y + dy[i];
      if (ch[x][y] & (1 << i)) {
        uf.unite(pos, pack(nx, ny));
      }
    }
  }
  if (last == -1)
    return false;
  return uf.size(last) == cnt;
}

bool dfs(int pos) {
  int x = pos / w + 1;
  int y = pos % w + 1;
  if (pos == h * w)
    return check();
  if (c[x][y])
    return dfs(pos + 1);

  for (int i = 0; i < 6; i++) {
    if ((can[x][y] & T[i]) != T[i])
      continue;
    if ((T[i] & need[x][y]) != need[x][y])
      continue;
    if (T[i] & ban[x][y])
      continue;
    ch[x][y] = T[i];

    for (int j = 0; j < 4; j++) {
      int nx = x + dx[j];
      int ny = y + dy[j];
      if (T[i] & (1 << j)) {
        need[nx][ny] ^= 1 << (j ^ 2);
      } else {
        ban[nx][ny] ^= 1 << (j ^ 2);
      }
    }

    if (dfs(pos + 1))
      return true;

    for (int j = 0; j < 4; j++) {
      int nx = x + dx[j];
      int ny = y + dy[j];
      if (T[i] & (1 << j)) {
        need[nx][ny] ^= 1 << (j ^ 2);
      } else {
        ban[nx][ny] ^= 1 << (j ^ 2);
      }
    }
  }

  return false;
}

bool solve() {
  fill_n(*can, 81, 0);
  fill_n(*need, 81, 0);
  fill_n(*ban, 81, 0);

  for (int i = 1; i <= h; i++) {
    for (int j = 1; j <= w; j++) {
      if (c[i][j]) {
        for (int k = 0; k < 4; k++) {
          int nx = i + dx[k];
          int ny = j + dy[k];
          ban[nx][ny] |= 1 << (k ^ 2);
        }
      } else {
        for (int k = 0; k < 4; k++) {
          int nx = i + dx[k];
          int ny = j + dy[k];
          if (!c[nx][ny]) {
            can[i][j] |= 1 << k;
          }
        }
      }
    }
  }

  return dfs(0);
}

int main() {
  while (scanf("%d %d", &w, &h), w) {
    fill_n(*c, 81, 1);
    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= w; j++) {
        scanf("%d", &c[i][j]);
      }
    }
    puts(solve() ? "Yes" : "No");
  }
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};

int h, w;
int grid[9][9];
int b;

int search(int i, int j) {
  grid[i][j] = 1;
  bool f = true;
  int res = 1;
  for (int dir = 0; dir < 4; dir++) {
    int nx = i + dx[dir];
    int ny = j + dy[dir];
    if (!grid[nx][ny]) {
      f = false;
      res = max(res, 1 + search(nx, ny));
    }
  }
  grid[i][j] = 0;
  return res;
}

bool solve() {
  if (b < 4)
    return false;
  for (int i = 1; i <= h; i++) {
    for (int j = 1; j <= w; j++) {
      if (grid[i][j] == 1)
        continue;
      return search(i, j) == b;
    }
  }
}

int main() {
  while (scanf("%d %d", &w, &h), w) {
    fill_n(*grid, 9 * 9, 1);
    b = 0;

    for (int i = 1; i <= h; i++) {
      for (int j = 1; j <= w; j++) {
        scanf("%d", &grid[i][j]);
        b += grid[i][j] ^ 1;
      }
    }

    puts(solve() ? "Yes" : "No");
  }
}