#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using Int = long long; template ostream &operator<<(ostream &os, const vector &as); template ostream &operator<<(ostream &os, const pair &a) { return os << "(" << a.first << ", " << a.second << ")"; }; template ostream &operator<<(ostream &os, const vector &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; } template void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; } template bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; } template bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; } #define COLOR(s) ("\x1b[" s "m") int root(vector &uf, int u) { return (uf[u] < 0) ? u : (uf[u] = root(uf, uf[u])); } bool connect(vector &uf, int u, int v) { u = root(uf, u); v = root(uf, v); if (u == v) return false; if (uf[u] > uf[v]) swap(u, v); uf[u] += uf[v]; uf[v] = u; return true; } using Op = pair, int>; vector transpose(vector ops) { for (Op &op : ops) swap(op.first.first, op.first.second); return ops; } vector solve(int M, int N) { vector> a(M, vector(N, -1)); vector ops; auto add = [&](int x, int y) -> void { ops.emplace_back(make_pair(x, y), a[x][y]); }; if (M == 1) { for (int y = 0; y < N; ++y) a[0][y] = (y + 1) / 2; for (int y = 0; y < N; ++y) add(0, y); return ops; } if (N == 1) return transpose(solve(N, M)); if (M == 2) { for (int x = 0; x < 2; ++x) for (int y = 0; y < N; ++y) a[x][y] = x; for (int y = 0; y < N; ++y) for (int x = 0; x < 2; ++x) add(x, y); return ops; } if (N == 2) return transpose(solve(N, M)); if (M == 3) { for (int x = 0; x < 2; ++x) a[x][0] = 0; for (int x = 1; x < 3; ++x) a[x][N - 1] = 1; for (int y = 1; y < N; ++y) a[0][y] = 2; for (int y = 0; y < 2; ++y) a[2][y] = 3; for (int y = 1; y < N - 1; ++y) a[1][y] = 0; for (int y = 2; y < N - 1; ++y) a[2][y] = 3 + (y - 1) / 2; add(0, 0); add(0, 1); add(1, 0); add(2, 0); add(1, 1); add(2, 1); for (int y = 2; y < N; y += 2) { add(0, y); add(1, y); add(0, y + 1); add(1, y + 1); add(2, y); add(2, y + 1); } return ops; } if (N == 3) return transpose(solve(N, M)); if (M % 2 == 0) { for (int x = 0; x < M; ++x) for (int y = 0; y < N; ++y) a[x][y] = x % 2; for (int x = 0; x < M - 1; ++x) a[x][0] = 0; for (int x = 1; x < M; ++x) a[x][N - 1] = 1; for (int y = 1; y < N; ++y) a[0][y] = 2; for (int y = 0; y < N - 1; ++y) a[M - 1][y] = 3; for (int x = 2; x < M - 1; ++x) a[x][N - 2] = 0; for (int x = 1; x < M - 2; ++x) a[x][1] = 1; for (int x = 0; x < M - 2; ++x) for (int y = 0; y < 2; ++y) add(x, y); for (int y = 0; y < 2; ++y) for (int x = M - 2; x < M; ++x) add(x, y); for (int x = 2; x < M; ++x) for (int y = N - 2; y < N; ++y) add(x, y); for (int y = N - 2; y < N; ++y) for (int x = 0; x < 2; ++x) add(x, y); for (int y = 2; y < N - 2; ++y) for (int x = 0; x < M; ++x) add(x, y); return ops; } if (N % 2 == 0) return transpose(solve(N, M)); assert(false); } void stress() { constexpr int LIM = 10; for (int M = 1; M <= LIM; ++M) for (int N = 1; N <= LIM; ++N) if ((M*N) % 2 == 0) { cerr << COLOR("93") << "M = " << M << ", N = " << N << COLOR() << endl; const auto ops = solve(M, N); if (!ops.size()) continue; assert((int)ops.size() == M*N); vector a(M, string(N, '?')), dir(M, string(N, '?')); for (const Op &op : ops) a[op.first.first][op.first.second] = '0' + op.second; for (int i = 0; i < M*N; i += 2) { const int x0 = ops[i + 0].first.first; const int y0 = ops[i + 0].first.second; const int x1 = ops[i + 1].first.first; const int y1 = ops[i + 1].first.second; assert(a[x0][y0] != a[x1][y1]); if (x0 == x1) { dir[x0][y0] = dir[x1][y1] = '-'; } else if (y0 == y1) { dir[x0][y0] = dir[x1][y1] = '|'; } else assert(false); } for (int x = 0; x < M; ++x) cout << a[x] << endl; cout << endl; for (int x = 0; x < M; ++x) cout << dir[x] << endl; cout << endl; int K = 0; for (const Op &op : ops) chmax(K, op.second + 1); for (int x = 0; x < M; ++x) for (int y = 0; y < N; ++y) { const int k = a[x][y] - '0'; assert(0 <= k); assert(k < K); } vector uf(M*N, -1); for (int x = 0; x < M; ++x) for (int y = 0; y < N; ++y) { if (x + 1 < M && a[x][y] == a[x + 1][y]) connect(uf, x * N + y, (x+1) * N + y); if (y + 1 < N && a[x][y] == a[x][y + 1]) connect(uf, x * N + y, x * N + (y+1)); } vector cs(K, 0); for (int x = 0; x < M; ++x) for (int y = 0; y < N; ++y) { const int r = x * N + y; if (uf[r] < 0) ++cs[a[x][y] - '0']; } for (int k = 0; k < K; ++k) assert(cs[k] == 1); } } int main() { #ifdef LOCAL stress(); #endif int M, N; for (; ~scanf("%d%d", &M, &N); ) { const auto ops = solve(M, N); int K = 0; for (const Op &op : ops) chmax(K, op.second + 1); printf("%d\n", K); for (int i = 0; i < M*N; ++i) { printf("%d %d %d%c", ops[i].first.first + 1, ops[i].first.second + 1, ops[i].second + 1, " \n"[i & 1]); } } return 0; }