Problem p00091 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>

//{{{ uf.hpp
#ifndef INCLUDE_UF_HPP
#define INCLUDE_UF_HPP
#include <algorithm>
#include <vector>
namespace orislib {
namespace ds {
//{{{ UF merge, same, root, size, count
struct UF {
  std::vector<int> data;
  int cnt;
  UF(int n) : data(n, -1), cnt(n) {}
  bool merge(int a, int b) {
    a = root(a);
    b = root(b);
    if (a != b) {
      cnt--;
      if (data[b] < data[a])
        std::swap(a, b);
      data[a] += data[b];
      data[b] = a;
    }
    return a != b;
  }
  bool same(int a, int b) { return root(a) == root(b); }
  int root(int a) { return data[a] >= 0 ? data[a] = root(data[a]) : a; }
  int size(int a) { return -data[root(a)]; }
  int count() { return cnt; }
};
//}}}
//{{{ UF2d merge, same, size, count
struct UF2d {
  UF uf;
  const int W, H;
  UF2d(int w, int h) : uf(w * h), W(w), H(h) {}
  bool merge(int ax, int ay, int bx, int by) {
    return uf.merge(ay * W + ax, by * W + bx);
  }
  bool same(int ax, int ay, int bx, int by) {
    return uf.same(ay * W + ax, by * W + bx);
  }
  int size(int x, int y) { return uf.size(y * W + x); }
  int count() { return uf.count(); }
};
//}}}
} // namespace ds
} // namespace orislib
#endif
//}}}

using namespace std;
using namespace orislib::ds;

typedef long long ll;
typedef long double ld;
typedef tuple<int, int> duo;
typedef tuple<int, int, int> tri;
const int dx[] = {0, 0, 0, 1, -1, 1, 1, -1, -1, 2, -2, 0, 0};
const int dy[] = {0, 1, -1, 0, 0, 1, -1, 1, -1, 0, 0, 2, -2};
const int Mod = 1000000000 + 0;
//{{{ templates
#define TT_ template <typename T> inline
#define TTF_ template <typename T, typename F> inline
TT_ T sq(T x) { return x * x; }
TT_ T In() {
  T x;
  cin >> x;
  return x;
}
TT_ void Out(T &x) { cout << x; }
TT_ void sort(T &v) { sort(begin(v), end(v)); }
TT_ void revs(T &v) { reverse(begin(v), end(v)); }
TT_ void uniq(T &v) {
  sort(v);
  v.erase(unique(begin(v), end(v)), end(v));
}
TT_ int ubnd(T &v, typename T::value_type &x) {
  return upper_bound(begin(v), end(v), x) - begin(v);
}
TT_ int lbnd(T &v, typename T::value_type &x) {
  return lower_bound(begin(v), end(v), x) - begin(v);
}
TTF_ void inpt(T &v, int n, F f) {
  for (v.reserve(n); n--; v.emplace_back(f()))
    ;
}
TTF_ void show(T &v, F f, string d = " ", string e = "\n") {
  int i = 0;
  for (auto &x : v)
    i++ && (cout << d), f(x);
  cout << e;
}
TT_ typename T::iterator minel(T &v) { return min_element(begin(v), end(v)); }
TT_ typename T::iterator maxel(T &v) { return max_element(begin(v), end(v)); }

inline void fast_io() {
  ios::sync_with_stdio(0);
  cin.tie(0);
}
inline int in() {
  int x;
  scanf("%d", &x);
  return x;
}
inline ll pow_mod(ll a, ll k, ll m) {
  ll r = 1;
  for (; k > 0; a = a * a % m, k >>= 1)
    if (k & 1)
      r = r * a % m;
  return r;
}
inline ll mod_inv(ll a, ll p) { return pow_mod(a, p - 2, p); }
//}}} priority_queue queue deque front stringstream max_element min_element
//insert count make_tuple

#define USE_HASH

struct Zhash {
  Zhash() {
    mt19937 mt;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        for (int s = 0; s < 256; s++) {
          rands[i][j][s] = mt();
        }
      }
    }
  }
  int hash(int data[10][10]) {
    int h = 0;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        h ^= rands[i][j][data[i][j]];
      }
    }
    return h;
  }
  int rands[10][10][256];
};

const int len[] = {5, 9, 13};

struct Board {
  Board() {
    memset(valid_table, 0, sizeof(valid_table));
    valid_table[0][0] = true;
    for (int t = 1; t <= 12; t++) {
      for (int v = 0; v <= 12 * 13; v++) {
        if (!valid_table[t - 1][v])
          continue;
        valid_table[t][v + 5] = true;
        valid_table[t][v + 9] = true;
        valid_table[t][v + 13] = true;
      }
    }
    memset(cnt, 0, sizeof(cnt));
  }
  void read() {
    N = in();
    tot = 0;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        data[i][j] = in();
        tot += data[i][j];
      }
    }
  }
  bool invalid(int x, int y) { return x < 0 || x >= 10 || y < 0 || y >= 10; }
  bool drop_ink(int x, int y, int t) {
    const int l = len[t];
    tot -= l;
    cnt[t]++;
    bool ok = tot >= 0 && valid_table[N - (cnt[0] + cnt[1] + cnt[2])][tot];
    for (int d = 0; d < l; d++) {
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny)) {
        ok = false;
        continue;
      }
      data[ny][nx]--;
      if (data[ny][nx] < 0)
        ok = false;
    }
    ans.emplace_back(x, y, t + 1);
    if (ok) {
#ifdef USE_HASH
      int h = zhash.hash(data);
      if (vis.count(h))
        return false;
      vis.insert(h);
      if (vis.size() >= 1000000u)
        vis.clear();
#endif
      UF2d uf(10, 10);
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          if (data[i][j] <= 0)
            continue;
          for (int d = 0; d < 5; d++) {
            int nx = j + dx[d], ny = i + dy[d];
            if (invalid(nx, ny))
              continue;
            if (data[ny][nx] <= 0)
              continue;
            uf.merge(j, i, nx, ny);
          }
        }
      }
      int mini = 128;
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          if (data[i][j] >= 1)
            mini = min(mini, uf.size(j, i));
        }
      }
      if (mini < 5)
        return false;
    }
    return ok;
  }
  void undo(int x, int y, int t) {
    const int l = len[t];
    tot += l;
    cnt[t]--;
    for (int d = 0; d < l; d++) {
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny))
        continue;
      data[ny][nx]++;
    }
    ans.pop_back();
  }
  bool solve() {
    if (cnt[0] + cnt[1] + cnt[2] == N)
      return true;
    for (int t = 0; t < 3; t++) {
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          bool ok = drop_ink(j, i, t);
          if (ok && solve())
            return true;
          undo(j, i, t);
        }
      }
    }
    return false;
  }
  int data[10][10];
  int cnt[3];
  int tot;
  int N;
  bool valid_table[13][13 * 13 + 1];
  unordered_set<int> vis;
  vector<tri> ans;
  Zhash zhash;
};

int main() {
  Board b;
  b.read();
  b.solve();
  for (const auto &a : b.ans) {
    cout << get<0>(a) << " " << get<1>(a) << " " << get<2>(a) << "\n";
  }
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>

//{{{ uf.hpp
#ifndef INCLUDE_UF_HPP
#define INCLUDE_UF_HPP
#include <algorithm>
#include <vector>
namespace orislib {
namespace ds {
//{{{ UF merge, same, root, size, count
struct UF {
  std::vector<int> data;
  int cnt;
  UF(int n) : data(n, -1), cnt(n) {}
  bool merge(int a, int b) {
    a = root(a);
    b = root(b);
    if (a != b) {
      cnt--;
      if (data[b] < data[a])
        std::swap(a, b);
      data[a] += data[b];
      data[b] = a;
    }
    return a != b;
  }
  bool same(int a, int b) { return root(a) == root(b); }
  int root(int a) { return data[a] >= 0 ? data[a] = root(data[a]) : a; }
  int size(int a) { return -data[root(a)]; }
  int count() { return cnt; }
};
//}}}
//{{{ UF2d merge, same, size, count
struct UF2d {
  UF uf;
  const int W, H;
  UF2d(int w, int h) : uf(w * h), W(w), H(h) {}
  bool merge(int ax, int ay, int bx, int by) {
    return uf.merge(ay * W + ax, by * W + bx);
  }
  bool same(int ax, int ay, int bx, int by) {
    return uf.same(ay * W + ax, by * W + bx);
  }
  int size(int x, int y) { return uf.size(y * W + x); }
  int count() { return uf.count(); }
};
//}}}
} // namespace ds
} // namespace orislib
#endif
//}}}

using namespace std;
using namespace orislib::ds;

typedef long long ll;
typedef long double ld;
typedef tuple<int, int> duo;
typedef tuple<int, int, int> tri;
const int dx[] = {0, 0, 0, 1, -1, 1, 1, -1, -1, 2, -2, 0, 0};
const int dy[] = {0, 1, -1, 0, 0, 1, -1, 1, -1, 0, 0, 2, -2};
const int Mod = 1000000000 + 0;
//{{{ templates
#define TT_ template <typename T> inline
#define TTF_ template <typename T, typename F> inline
TT_ T sq(T x) { return x * x; }
TT_ T In() {
  T x;
  cin >> x;
  return x;
}
TT_ void Out(T &x) { cout << x; }
TT_ void sort(T &v) { sort(begin(v), end(v)); }
TT_ void revs(T &v) { reverse(begin(v), end(v)); }
TT_ void uniq(T &v) {
  sort(v);
  v.erase(unique(begin(v), end(v)), end(v));
}
TT_ int ubnd(T &v, typename T::value_type &x) {
  return upper_bound(begin(v), end(v), x) - begin(v);
}
TT_ int lbnd(T &v, typename T::value_type &x) {
  return lower_bound(begin(v), end(v), x) - begin(v);
}
TTF_ void inpt(T &v, int n, F f) {
  for (v.reserve(n); n--; v.emplace_back(f()))
    ;
}
TTF_ void show(T &v, F f, string d = " ", string e = "\n") {
  int i = 0;
  for (auto &x : v)
    i++ && (cout << d), f(x);
  cout << e;
}
TT_ typename T::iterator minel(T &v) { return min_element(begin(v), end(v)); }
TT_ typename T::iterator maxel(T &v) { return max_element(begin(v), end(v)); }

inline void fast_io() {
  ios::sync_with_stdio(0);
  cin.tie(0);
}
inline int in() {
  int x;
  scanf("%d", &x);
  return x;
}
inline ll pow_mod(ll a, ll k, ll m) {
  ll r = 1;
  for (; k > 0; a = a * a % m, k >>= 1)
    if (k & 1)
      r = r * a % m;
  return r;
}
inline ll mod_inv(ll a, ll p) { return pow_mod(a, p - 2, p); }
//}}} priority_queue queue deque front stringstream max_element min_element
//insert count make_tuple

#define USE_HASH

struct Zhash {
  Zhash() {
    mt19937 mt;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        for (int s = 0; s < 256; s++) {
          rands[i][j][s] = mt();
        }
      }
    }
  }
  int hash(int data[10][10]) {
    int h = 0;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        h ^= rands[i][j][data[i][j]];
      }
    }
    return h;
  }
  int rands[10][10][256];
};

const int len[] = {5, 9, 13};

struct Board {
  Board() {
    memset(valid_table, 0, sizeof(valid_table));
    valid_table[0][0] = true;
    for (int t = 1; t <= 12; t++) {
      for (int v = 0; v <= 12 * 13; v++) {
        if (!valid_table[t - 1][v])
          continue;
        valid_table[t][v + 5] = true;
        valid_table[t][v + 9] = true;
        valid_table[t][v + 13] = true;
      }
    }
    memset(cnt, 0, sizeof(cnt));
  }
  void read() {
    N = in();
    tot = 0;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        data[i][j] = in();
        tot += data[i][j];
      }
    }
  }
  bool invalid(int x, int y) { return x < 0 || x >= 10 || y < 0 || y >= 10; }
  bool drop_ink(int x, int y, int t) {
    const int l = len[t];
    tot -= l;
    cnt[t]++;
    bool ok = tot >= 0 && valid_table[N - (cnt[0] + cnt[1] + cnt[2])][tot];
    for (int d = 0; d < l; d++) {
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny)) {
        ok = false;
        continue;
      }
      data[ny][nx]--;
      if (data[ny][nx] < 0)
        ok = false;
    }
    ans.emplace_back(x, y, t + 1);
    if (ok) {
#ifdef USE_HASH
      int h = zhash.hash(data);
      if (vis.count(h))
        return false;
      vis.insert(h);
      if (vis.size() >= 1000000u)
        vis.clear();
#endif
      UF2d uf(10, 10);
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          if (data[i][j] <= 0)
            continue;
          for (int d = 0; d < 5; d++) {
            int nx = j + dx[d], ny = i + dy[d];
            if (invalid(nx, ny))
              continue;
            if (data[ny][nx] <= 0)
              continue;
            uf.merge(j, i, nx, ny);
          }
        }
      }
      int mini = 128;
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          if (data[i][j] >= 1)
            mini = min(mini, uf.size(j, i));
        }
      }
      if (mini < 5)
        return false;
    }
    return ok;
  }
  void undo(int x, int y, int t) {
    const int l = len[t];
    tot += l;
    cnt[t]--;
    for (int d = 0; d < l; d++) {
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny))
        continue;
      data[ny][nx]++;
    }
    ans.pop_back();
  }
  bool solve() {
    if (cnt[0] + cnt[1] + cnt[2] == N)
      return true;
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) {
        if (!data[i][j])
          continue;
        bool ok;
        ok = drop_ink(j, i + 1, 0);
        if (ok && solve())
          return true;
        undo(j, i + 1, 0);
        ok = drop_ink(j + 1, i + 1, 1);
        if (ok && solve())
          return true;
        undo(j + 1, i + 1, 1);
        ok = drop_ink(j, i + 2, 2);
        if (ok && solve())
          return true;
        undo(j, i + 2, 2);
        return false;
      }
    }
    return true;
  }
  int data[10][10];
  int cnt[3];
  int tot;
  int N;
  bool valid_table[13][13 * 13 + 1];
  unordered_set<int> vis;
  vector<tri> ans;
  Zhash zhash;
};

int main() {
  Board b;
  b.read();
  b.solve();
  for (const auto &a : b.ans) {
    cout << get<0>(a) << " " << get<1>(a) << " " << get<2>(a) << "\n";
  }
  return 0;
}