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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef unsigned long long ull;

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int W, H, C;
int grid[10][10];
vector<int> G[100];
unordered_set<ull> used[100];
bool dfs(int u, ull s) {
  if (s == (1ULL << C) - 1) {
    for (auto v : G[0])
      if (v == u)
        return true;
    return false;
  }
  if (used[u].count(s))
    return false;

  // u = 0 にいけない
  {
    bool any = true;
    for (auto v : G[0])
      if (!(s & (1ULL << v)))
        any = false;
    if (any)
      return false;
  }

  // のこりの頂点の次数が1以下の個数を数える
  int low_degrees = 0;
  REP(i, C) if (!(s & (1ULL << i))) {
    int deg = 0;
    for (auto v : G[i])
      if (!(s & (1ULL << v)))
        deg++;
    if (deg <= 1)
      low_degrees += 1;
    if (low_degrees >= 3)
      return false;
  }

  used[u].insert(s);

  // のこりの頂点が連結かどうか
  queue<int> que;
  ull used_s = s;
  que.push(u);
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    REP(i, G[u].size()) {
      int v = G[u][i];
      if (used_s & (1ULL << v))
        continue;
      used_s |= 1ULL << v;
      que.push(v);
    }
  }
  if (used_s != (1ULL << C) - 1) {
    return false;
  }

  for (auto v : G[u]) {
    if (s & (1ULL << v))
      continue;
    if (dfs(v, s | (1ULL << v)))
      return true;
  }
  return false;
}
bool dfs_naive(int u, ull s) {
  if (s == (1ULL << C) - 1) {
    for (auto v : G[0])
      if (v == u)
        return true;
    return false;
  }
  for (auto v : G[u]) {
    if (s & (1ULL << v))
      continue;
    if (dfs_naive(v, s | (1ULL << v))) {
      // printf("%d->%d\\n", u, v);
      return true;
    }
  }
  return false;
}

bool solve(int W, int H) {
  C = 0;

  int id[10][10];
  REP(y, H) REP(x, W) {
    if (grid[y][x] == 0) {
      id[y][x] = C++;
    }
  }

  REP(i, C) G[i].clear();
  REP(y, H) REP(x, W) if (grid[y][x] == 0) {
    REP(r, 4) {
      int nx = x + dx[r];
      int ny = y + dy[r];
      if (valid(nx, ny, W, H) && grid[ny][nx] == 0)
        G[id[y][x]].push_back(id[ny][nx]);
    }
  }

  /*
  REP(i, 100) used[i].clear();
  if(dfs(0, 1) != dfs_naive(0, 1)){
      REP(y, H) {
          REP(x, W) cout << grid[y][x] << " ";
          cout << endl;
      }
      REP(i, 100) used[i].clear();
      cout << dfs(0, 1) << endl;
      cout << dfs_naive(0, 1) << endl;
      assert(false);
  }
  */

  REP(i, C) used[i].clear();
  if (C > 3 && (C == 1 || dfs(0, 1))) {
    return true;
  } else {
    return false;
  }
}

int main() {
  /*
  REP(_, 100000){
      int W = rand() % 5 + 1;
      int H = rand() % 5 + 1;
      REP(y, H) REP(x, W) grid[y][x] = rand() % 2;
      solve(W, H);
  }
  */
  while (cin >> W >> H && W) {
    REP(y, H) REP(x, W) cin >> grid[y][x];
    if (solve(W, H))
      cout << "Yes" << endl;
    else
      cout << "No" << endl;
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \\
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef unsigned long long ull;

int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int W, H, C;
int grid[10][10];
vector<int> G[100];
unordered_set<ull> used[100];
bool dfs(int u, ull s) {
  if (s == (1ULL << C) - 1) {
    for (auto v : G[0])
      if (v == u)
        return true;
    return false;
  }
  if (used[u].count(s))
    return false;
  used[u].insert(s);

  // u = 0 にいけない
  {
    bool any = true;
    for (auto v : G[0])
      if (!(s & (1ULL << v)))
        any = false;
    if (any)
      return false;
  }

  // のこりの頂点の次数が1以下の個数を数える
  int low_degrees = 0;
  REP(i, C) if (!(s & (1ULL << i))) {
    int deg = 0;
    for (auto v : G[i])
      if (!(s & (1ULL << v)))
        deg++;
    if (deg <= 1)
      low_degrees += 1;
    if (low_degrees >= 3)
      return false;
  }

  // のこりの頂点が連結かどうか
  queue<int> que;
  ull used_s = s;
  que.push(u);
  while (!que.empty()) {
    int u = que.front();
    que.pop();
    REP(i, G[u].size()) {
      int v = G[u][i];
      if (used_s & (1ULL << v))
        continue;
      used_s |= 1ULL << v;
      que.push(v);
    }
  }
  if (used_s != (1ULL << C) - 1) {
    return false;
  }

  for (auto v : G[u]) {
    if (s & (1ULL << v))
      continue;
    if (dfs(v, s | (1ULL << v)))
      return true;
  }
  return false;
}
bool dfs_naive(int u, ull s) {
  if (s == (1ULL << C) - 1) {
    for (auto v : G[0])
      if (v == u)
        return true;
    return false;
  }
  for (auto v : G[u]) {
    if (s & (1ULL << v))
      continue;
    if (dfs_naive(v, s | (1ULL << v))) {
      // printf("%d->%d\\n", u, v);
      return true;
    }
  }
  return false;
}

bool solve(int W, int H) {
  C = 0;

  int id[10][10];
  REP(y, H) REP(x, W) {
    if (grid[y][x] == 0) {
      id[y][x] = C++;
    }
  }

  REP(i, C) G[i].clear();
  REP(y, H) REP(x, W) if (grid[y][x] == 0) {
    REP(r, 4) {
      int nx = x + dx[r];
      int ny = y + dy[r];
      if (valid(nx, ny, W, H) && grid[ny][nx] == 0)
        G[id[y][x]].push_back(id[ny][nx]);
    }
  }

  /*
  REP(i, 100) used[i].clear();
  if(dfs(0, 1) != dfs_naive(0, 1)){
      REP(y, H) {
          REP(x, W) cout << grid[y][x] << " ";
          cout << endl;
      }
      REP(i, 100) used[i].clear();
      cout << dfs(0, 1) << endl;
      cout << dfs_naive(0, 1) << endl;
      assert(false);
  }
  */

  REP(i, C) used[i].clear();
  if (C > 0 && (C == 1 || dfs(0, 1))) {
    return true;
  } else {
    return false;
  }
}

int main() {
  /*
  REP(_, 100000){
      int W = rand() % 5 + 1;
      int H = rand() % 5 + 1;
      REP(y, H) REP(x, W) grid[y][x] = rand() % 2;
      solve(W, H);
  }
  */
  while (cin >> W >> H && W) {
    REP(y, H) REP(x, W) cin >> grid[y][x];
    if (solve(W, H))
      cout << "Yes" << endl;
    else
      cout << "No" << endl;
  }
  return 0;
}