#include <bits/stdc++.h>
using namespace std;
template <class T>
inline T min(T &a, T &b) {
  return a < b ? a : b;
}
template <class T>
inline T max(T &a, T &b) {
  return a > b ? a : b;
}
template <class T>
void read(T &x) {
  char ch;
  while ((ch = getchar()) && !isdigit(ch))
    ;
  x = ch - '0';
  while ((ch = getchar()) && isdigit(ch)) x = x * 10 + ch - '0';
}
const int Range = 4;
const int Range2 = 7;
const int eps = 0;
const int N = 2000;
const int U[8] = {0, 0, 1, -1, 1, 1, -1, -1};
const int V[8] = {1, -1, 0, 0, 1, -1, 1, -1};
queue<pair<int, int> > Q;
int sun, Sun[N][N], n, m, dt[N][N], rg[N][N], vis[N][N], ans[N];
int In(int x, int a, int b) { return x >= a && x <= b; }
void Fill_Sun(int Sx, int Sy) {
  Q.push(make_pair(Sx, Sy));
  Sun[Sx][Sy] = sun;
  while (Q.size()) {
    pair<int, int> c = Q.front();
    Q.pop();
    for (int i = 0; i <= 7; i++) {
      int x = c.first + U[i], y = c.second + V[i];
      if (In(x, 1, n) && In(y, 1, m) && !Sun[x][y] && dt[x][y] == 1) {
        Sun[x][y] = sun;
        Q.push(make_pair(x, y));
      }
    }
  }
}
void Sign_Sun() {
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      if (!Sun[i][j] && dt[i][j] == 1) ++sun, Fill_Sun(i, j);
}
void Sign_Green() {
  for (int i = 1; i <= n; i++) {
    if (dt[i][1] == 0) Q.push(make_pair(i, 1)), rg[i][1] = Range, vis[i][1] = 1;
    if (dt[i][m] == 0) Q.push(make_pair(i, m)), rg[i][m] = Range, vis[i][m] = 1;
  }
  for (int i = 1; i <= m; i++) {
    if (dt[1][i] == 0) Q.push(make_pair(1, i)), rg[1][i] = Range, vis[1][i] = 1;
    if (dt[n][i] == 0) Q.push(make_pair(n, i)), rg[n][i] = Range, vis[n][i] = 1;
  }
  while (Q.size()) {
    pair<int, int> c = Q.front();
    Q.pop();
    if (rg[c.first][c.second] == 0) continue;
    for (int i = 0; i <= 7; i++) {
      int x = c.first + U[i], y = c.second + V[i];
      if (In(x, 1, n) && In(y, 1, m)) {
        if (dt[x][y] == 0 && !vis[x][y])
          Q.push(make_pair(x, y)), rg[x][y] = Range, vis[x][y] = 1;
        if (dt[x][y] == 1 && rg[x][y] < rg[c.first][c.second] - 1)
          Q.push(make_pair(x, y)), vis[x][y] = 1,
                                   rg[x][y] = rg[c.first][c.second] - 1;
      }
    }
  }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      if (vis[i][j] == 1 && dt[i][j] == 1) dt[i][j] = 2;
}
void Sign_Red() {
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      rg[i][j] = 0;
      vis[i][j] = 0;
      if (dt[i][j] == 1)
        Q.push(make_pair(i, j)), rg[i][j] = Range2, vis[i][j] = 1;
    }
  while (Q.size()) {
    pair<int, int> c = Q.front();
    Q.pop();
    if (rg[c.first][c.second] == 0) continue;
    for (int i = 0; i <= 7; i++) {
      int x = c.first + U[i], y = c.second + V[i];
      if (In(x, 1, n) && In(y, 1, m)) {
        if (dt[x][y] == 1 && !vis[x][y])
          Q.push(make_pair(x, y)), rg[x][y] = Range2, vis[x][y] = 1;
        if (dt[x][y] == 2 && rg[x][y] < rg[c.first][c.second] - 1)
          Q.push(make_pair(x, y)), vis[x][y] = 1,
                                   rg[x][y] = rg[c.first][c.second] - 1;
      }
    }
  }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (vis[i][j] == 1 && dt[i][j] == 2) dt[i][j] = 3;
}
int gs;
void Remark(int x, int y) {
  gs++;
  dt[x][y] = 3;
  for (int i = 0; i <= 7; i++)
    if (In(x + U[i], 1, n) && In(y + V[i], 1, m) && dt[x + U[i]][y + V[i]] == 2)
      Remark(x + U[i], y + V[i]);
}
void Get_Answer() {
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (dt[i][j] == 2) {
        gs = 0;
        Remark(i, j);
        if (gs > eps) ans[Sun[i][j]]++;
      }
}
void Print() {
  printf("%d\n", sun);
  sort(ans + 1, ans + sun + 1);
  for (int i = 1; i <= sun; i++) printf("%d ", ans[i]);
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) scanf("%d", &dt[i][j]);
  n = max(n, m);
  m = max(n, m);
  Sign_Sun();
  Sign_Green();
  Sign_Red();
  Get_Answer();
  Print();
}
