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

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)

using namespace std;

struct Edge {
  int next, dir;
};

int w, h, sp;
bool field[20][20];
vector<Edge> G[500];
bool visited[500], used[500];
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};

bool isValid(int x, int y) { return 0 <= x && x < w && 0 <= y && y < h; }

bool check() {
  rep(i, h * w) used[i] = false;
  rep(i, h) rep(j, w) if (field[i][j] || visited[j + i * w]) used[j + i * w] =
      true;
  int cnt = 0;
  rep(i, h) rep(j, w) if (!used[i]) {
    if (cnt)
      return false;
    ++cnt;
    deque<int> deq;
    deq.push_back(j + i * w);
    while (!deq.empty()) {
      int cur = deq.front();
      deq.pop_front();
      rep(k, 4) {
        int nx = cur % w + dx[k], ny = cur / w + dy[k];
        if (!isValid(nx, ny))
          continue;
        if (used[ny * w + nx])
          continue;
        used[ny * w + nx] = true;
        deq.push_back(nx + ny * w);
      }
    }
  }
  return true;
}

bool check2(int cur) {
  rep(i, h * w) used[i] = false;
  rep(i, h) rep(j, w) if (field[i][j] || visited[j + i * w]) used[j + i * w] =
      true;
  deque<int> deq;
  deq.push_back(cur);
  used[sp] = false;
  used[cur] = true;
  while (!deq.empty()) {
    int v = deq.front();
    deq.pop_front();
    if (v == sp)
      return true;
    rep(i, (int)G[v].size()) {
      int next = G[v][i].next;
      if (used[next])
        continue;
      used[next] = true;
      deq.push_back(next);
    }
  }
  return false;
}

int counter[30][30];
bool check3(int cur) {
  rep(i, h) rep(j, w) counter[i][j] = 0;
  rep(i, h) rep(j, w) if (!field[i][j] && !visited[i * w + j]) {
    rep(k, 4) {
      int nx = j + dx[k], ny = i + dy[k];
      if (!isValid(nx, ny))
        continue;
      if (field[ny][nx])
        continue;
      if (visited[ny * w + nx])
        continue;
      ++counter[i][j];
    }
    if (counter[i][j] == 1) {
      int outer = 0;
      int diff_x = abs(sp % w - j), diff_y = abs(sp / w - i);
      if (diff_x + diff_y <= 1)
        ++outer;
      diff_x = abs(cur % w - j), diff_y = abs(cur / w - i);
      if (diff_x + diff_y <= 1)
        ++outer;
      if (outer == 0) {
        // cout << "OUT " << j << "," << i << endl;
        // cout << "cur = " << cur%w << "," << cur/w << endl;
        return false;
      }
    }
  }
  return true;
}

bool dfs(int cur, int remain) {
  /*
  puts("");
  cout << remain << endl;
  rep(i,h) {
    rep(j,w) {
      if( field[i][j] ) cout << "X";
      else cout << visited[i*w+j];
    }
    puts("");
  }
  */

  if (remain == 0) {
    int diff_x = abs(cur % w - sp % w), diff_y = abs(cur / w - sp / w);
    /*
    cout << sp%w << "," << sp/w << endl;
    cout << cur%w << "," << cur/w << endl;
    cout << "DIFF = " << diff_x << " + " << diff_y << endl;
    */
    if (diff_x + diff_y == 1)
      return true;
    return false;
  }

  rep(i, (int)G[cur].size()) {
    int next = G[cur][i].next;
    if (visited[next])
      continue;
    // if( !check() ) continue;
    if (!check2(next))
      continue;
    if (!check3(next))
      continue;
    visited[next] = true;
    if (dfs(next, remain - 1))
      return true;
    visited[next] = false;
  }

  return false;
}

void compute() {
  sp = -1;
  rep(i, h * w) G[i].clear(), visited[i] = false;
  rep(y, h) rep(x, w) if (!field[y][x]) {
    if (sp == -1)
      sp = x + y * w;
    rep(i, 4) {
      int nx = x + dx[i], ny = y + dy[i];
      if (!isValid(nx, ny))
        continue;
      if (field[ny][nx])
        continue;
      G[x + y * w].push_back((Edge){nx + ny * w, i});
    }
  }

  rep(i, h * w) if (G[i].size() == 1) {
    puts("No");
    return;
  }

  int remain = 0;
  rep(i, h) rep(j, w) if (!field[i][j])++ remain;
  // assert( sp != -1 );
  visited[sp] = true;
  if ((remain & 1) || remain == 0) {
    puts("No");
    return;
  }
  puts(dfs(sp, remain - 1) ? "Yes" : "No");
}

int main() {
  while (cin >> w >> h, w | h) {
    rep(i, h) rep(j, w) cin >> field[i][j];
    compute();
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>

#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)

using namespace std;

struct Edge {
  int next, dir;
};

int w, h, sp;
bool field[20][20];
vector<Edge> G[500];
bool visited[500], used[500];
int dx[] = {0, 1, 0, -1};
int dy[] = {-1, 0, 1, 0};

bool isValid(int x, int y) { return 0 <= x && x < w && 0 <= y && y < h; }

bool check() {
  rep(i, h * w) used[i] = false;
  rep(i, h) rep(j, w) if (field[i][j] || visited[j + i * w]) used[j + i * w] =
      true;
  int cnt = 0;
  rep(i, h) rep(j, w) if (!used[i]) {
    if (cnt)
      return false;
    ++cnt;
    deque<int> deq;
    deq.push_back(j + i * w);
    while (!deq.empty()) {
      int cur = deq.front();
      deq.pop_front();
      rep(k, 4) {
        int nx = cur % w + dx[k], ny = cur / w + dy[k];
        if (!isValid(nx, ny))
          continue;
        if (used[ny * w + nx])
          continue;
        used[ny * w + nx] = true;
        deq.push_back(nx + ny * w);
      }
    }
  }
  return true;
}

bool check2(int cur) {
  rep(i, h * w) used[i] = false;
  rep(i, h) rep(j, w) if (field[i][j] || visited[j + i * w]) used[j + i * w] =
      true;
  deque<int> deq;
  deq.push_back(cur);
  used[sp] = false;
  used[cur] = true;
  while (!deq.empty()) {
    int v = deq.front();
    deq.pop_front();
    if (v == sp)
      return true;
    rep(i, (int)G[v].size()) {
      int next = G[v][i].next;
      if (used[next])
        continue;
      used[next] = true;
      deq.push_back(next);
    }
  }
  return false;
}

bool dfs(int cur, int remain) {
  if (remain == 0) {
    int tx = cur % w + dx[0], ty = cur / w + dy[0];
    if (!isValid(tx, ty))
      return false;
    if (tx + ty * w != sp)
      return false;
    return true;
  }

  rep(i, (int)G[cur].size()) {
    int next = G[cur][i].next;
    if (visited[next])
      continue;
    // if( !check() ) continue;
    if (!check2(next))
      continue;
    visited[next] = true;
    if (dfs(next, remain - 1))
      return true;
    visited[next] = false;
  }

  return false;
}

void compute() {
  int sp = -1;
  rep(i, h * w) G[i].clear(), visited[i] = false;
  rep(y, h) rep(x, w) if (!field[y][x]) {
    if (sp == -1)
      sp = x + y * w;
    rep(i, 4) {
      int nx = x + dx[i], ny = y + dy[i];
      if (!isValid(nx, ny))
        continue;
      if (field[ny][nx])
        continue;
      G[x + y * w].push_back((Edge){nx + ny * w, i});
    }
  }

  rep(i, h * w) if (G[i].size() == 1) {
    puts("No");
    return;
  }

  int remain = 0;
  rep(i, h) rep(j, w) if (!field[i][j])++ remain;
  // assert( sp != -1 );
  visited[sp] = true;
  if ((remain & 1) || remain == 0) {
    puts("No");
    return;
  }
  puts(dfs(sp, remain - 1) ? "Yes" : "No");
}

int main() {
  while (cin >> w >> h, w | h) {
    rep(i, h) rep(j, w) cin >> field[i][j];
    compute();
  }
  return 0;
}