#include<iostream>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;

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

const int MAX_N = 1600;
int W, H;
char img[MAX_N][MAX_N];
char buf[MAX_N][MAX_N];
char tmp[MAX_N][MAX_N];
int dist[MAX_N][MAX_N];

const char BACKGROUND = 0;
const char SUN = 1;

vector<int> v;

void dfs(int i, int j, int id) {
  if (buf[i][j] == 1) {
      buf[i][j] = id;
      v.push_back(i * 10000 + j);
      for (int di = -1; di <= 1; di++)
          for (int dj = -1; dj <= 1; dj++) {
              if (di == 0 && dj == 0) continue;
              dfs(i + di, j + dj, id);
          }

  }
}

int main() {
  scanf("%d%d", &H, &W);

  int x;
  REP(i, H) REP(j, W) {
      scanf("%d", &x);
      img[i][j] = x;
  }

  REP(i, H) REP(j, W) buf[i][j] = img[i][j];

  REP(step, 1) {
      REP(i, H) REP(j, W) tmp[i][j] = img[i][j];
      for (int i = 1; i < H - 1; i++)
          for (int j = 1; j < W - 1; j++)
          {
              if (img[i][j] == 0) {
                  tmp[i+1][j+1] = 0;
                  tmp[i+1][j] = 0;
                  tmp[i+1][j-1] = 0;
                  tmp[i][j+1] = 0;
                  tmp[i][j-1] = 0;
                  tmp[i-1][j+1] = 0;
                  tmp[i-1][j] = 0;
                  tmp[i-1][j-1] = 0;
              }
          }
      REP(i, H) REP(j, W) img[i][j] = tmp[i][j];
  }

  REP(step, 1) {
      REP(i, H) REP(j, W) tmp[i][j] = buf[i][j];
      for (int i = 1; i < H - 1; i++)
          for (int j = 1; j < W - 1; j++)
          {
              if (buf[i][j] == 0) {
                  tmp[i+1][j+1] = 0;
                  tmp[i+1][j] = 0;
                  tmp[i+1][j-1] = 0;
                  tmp[i][j+1] = 0;
                  tmp[i][j-1] = 0;
                  tmp[i-1][j+1] = 0;
                  tmp[i-1][j] = 0;
                  tmp[i-1][j-1] = 0;
              }
          }
      REP(i, H) REP(j, W) buf[i][j] = tmp[i][j];
  }

  REP(i, H) {
      REP(j, W) cerr << (buf[i][j] == 0 ? "." : "#")  ;
      cerr << endl;
  }

  int id = 8;

  vector<int> ans;

  REP(i, H) REP(j, W) {
      if (buf[i][j] == 1) {

          v.clear();
          ++id;
          dfs(i, j, id);

          deque<int> deque;

          for (int k = 0; k < (int)v.size(); k++) {
              int r = v[k] / 10000;
              int c = v[k] % 10000;

              int oc = 0;
              for (int di = -1; di <= 1; di++)
                  for (int dj = -1; dj <= 1; dj++) {
                      if (di == 0 && dj == 0) continue;
                      if (buf[r + di][c + dj] == id) oc++;
                  }

              if (oc >= 8) {
                  dist[r][c] = 0;
                  deque.push_back(v[k]);
              } else {
                  dist[r][c] = -1;
              }
          }

          vector<int> rs, cs;
          while (deque.size() > 0) {
              int pos = deque.front();
              deque.pop_front();
              int r = pos / 10000;
              int c = pos % 10000;
              if (dist[r][c] >= 6) {
                  rs.push_back(r);
                  cs.push_back(c);
                  continue;
              }

              for (int di = -1; di <= 1; di++) {
                  for (int dj = -1; dj <= 1; dj++) {
                      if (di == 0 && dj == 0) continue;
                      int dr = r + di;
                      int dc = c + dj;
                      if (buf[dr][dc] == id) {
                          if (dist[dr][dc] == -1) {
                              deque.push_back(dr * 10000 + dc);
                              dist[dr][dc] = dist[r][c] + 1;
                              if (dist[r][c] >= 4) goto BK;
                          }

                      }
                  }
              }
          BK:;

          }

          int m = rs.size();

          vector<int> ids(m);
          for (int i = 0; i < m; i++) ids[i] = i;

          for (int i = 0; i < m; i++) {
              for (int j = i+1; j < m; j++) {
                  if (abs(rs[i] - rs[j]) + abs(cs[i] - cs[j]) <= 1) {
                      int a = ids[i];
                      int b = ids[j];
                      REP(k, m) {
                          if (ids[k] == b)
                              ids[k] = a;
                      }
                  }
              }
          }

          set<int> s;
          REP(i, m) s.insert(ids[i]);
          ans.push_back(s.size());
//          cout << s.size() << endl;

      }
  }

  sort(ans.begin(), ans.end());
  cout << ans.size() << endl;

  for (int i = 0; i < (int)ans.size(); i++) {
      if (i > 0) cout << " ";
      cout << ans[i];
  }
  cout << endl;
}


#include<iostream>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<cstdio>
#include<cstring>
using namespace std;

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

const int MAX_N = 1600;
int W, H;
char img[MAX_N][MAX_N];
char buf[MAX_N][MAX_N];
char tmp[MAX_N][MAX_N];
int dist[MAX_N][MAX_N];

const char BACKGROUND = 0;
const char SUN = 1;

vector<int> v;

void dfs(int i, int j, int id) {
  if (buf[i][j] == 1) {
      buf[i][j] = id;
      v.push_back(i * 10000 + j);
      for (int di = -1; di <= 1; di++)
          for (int dj = -1; dj <= 1; dj++) {
              if (di == 0 && dj == 0) continue;
              dfs(i + di, j + dj, id);
          }

  }
}

int main() {
  scanf("%d%d", &H, &W);

  int x;
  REP(i, H) REP(j, W) {
      scanf("%d", &x);
      img[i][j] = x;
  }

  REP(i, H) REP(j, W) buf[i][j] = img[i][j];

  REP(step, 1) {
      REP(i, H) REP(j, W) tmp[i][j] = img[i][j];
      for (int i = 1; i < H - 1; i++)
          for (int j = 1; j < W - 1; j++)
          {
              if (img[i][j] == 0) {
                  tmp[i+1][j+1] = 0;
                  tmp[i+1][j] = 0;
                  tmp[i+1][j-1] = 0;
                  tmp[i][j+1] = 0;
                  tmp[i][j-1] = 0;
                  tmp[i-1][j+1] = 0;
                  tmp[i-1][j] = 0;
                  tmp[i-1][j-1] = 0;
              }
          }
      REP(i, H) REP(j, W) img[i][j] = tmp[i][j];
  }

  REP(step, 1) {
      REP(i, H) REP(j, W) tmp[i][j] = buf[i][j];
      for (int i = 1; i < H - 1; i++)
          for (int j = 1; j < W - 1; j++)
          {
              if (buf[i][j] == 0) {
                  tmp[i+1][j+1] = 0;
                  tmp[i+1][j] = 0;
                  tmp[i+1][j-1] = 0;
                  tmp[i][j+1] = 0;
                  tmp[i][j-1] = 0;
                  tmp[i-1][j+1] = 0;
                  tmp[i-1][j] = 0;
                  tmp[i-1][j-1] = 0;
              }
          }
      REP(i, H) REP(j, W) buf[i][j] = tmp[i][j];
  }

  REP(i, H) {
      REP(j, W) cerr << (buf[i][j] == 0 ? "." : "#")  ;
      cerr << endl;
  }

  int id = 8;

  vector<int> ans;

  REP(i, H) REP(j, W) {
      if (buf[i][j] == 1) {

          v.clear();
          ++id;
          dfs(i, j, id);

          deque<int> deque;

          for (int k = 0; k < (int)v.size(); k++) {
              int r = v[k] / 10000;
              int c = v[k] % 10000;

              int oc = 0;
              for (int di = -1; di <= 1; di++)
                  for (int dj = -1; dj <= 1; dj++) {
                      if (di == 0 && dj == 0) continue;
                      if (buf[r + di][c + dj] == id) oc++;
                  }

              if (oc >= 8) {
                  dist[r][c] = 0;
                  deque.push_back(v[k]);
              } else {
                  dist[r][c] = -1;
              }
          }

          vector<int> rs, cs;
          while (deque.size() > 0) {
              int pos = deque.front();
              deque.pop_front();
              int r = pos / 10000;
              int c = pos % 10000;
              if (dist[r][c] >= 6) {
                  rs.push_back(r);
                  cs.push_back(c);
                  continue;
              }

              for (int di = -1; di <= 1; di++) {
                  for (int dj = -1; dj <= 1; dj++) {
                      if (di == 0 && dj == 0) continue;
                      int dr = r + di;
                      int dc = c + dj;
                      if (buf[dr][dc] == id) {
                          if (dist[dr][dc] == -1) {
                              deque.push_back(dr * 10000 + dc);
                              dist[dr][dc] = dist[r][c] + 1;
                              if (dist[r][c] >= 4) goto BK;
                          }

                      }
                  }
              }
          BK:;

          }

          int m = rs.size();

          vector<int> ids(m);
          for (int i = 0; i < m; i++) ids[i] = i;

          for (int i = 0; i < m; i++) {
              for (int j = i+1; j < m; j++) {
                  if (abs(rs[i] - rs[j]) + abs(cs[i] - cs[j]) <= 1) {
                      int a = ids[i];
                      int b = ids[j];
                      REP(k, m) {
                          if (ids[k] == b)
                              ids[k] = a;
                      }
                  }
              }
          }

          set<int> s;
          REP(i, m) s.insert(ids[i]);
          ans.push_back(s.size());
//          cout << s.size() << endl;

      }
  }

  sort(ans.begin(), ans.end());
  cout << ans.size() << endl;

  for (int i = 0; i < (int)ans.size(); i++) {
      if (i > 0) cout << " ";
      cout << ans[i];
  }
  cout << endl;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <ctime>
#include <cstring>
#include <cassert>
#include <bitset>
#include <sstream>
#include <queue>

using namespace std;

#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define ford(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define fs first
#define sc second
#define last(a) int(a.size() - 1)
#define all(a) a.begin(), a.end()
#define seta(a,x) memset (a, x, sizeof (a))
#define I (int)

typedef long long int64;
typedef pair <int, int> pii;
typedef long double ldb;

const long double eps = 1e-9;
const int inf = (1 << 30) - 1;
const int64 inf64 = ((int64)1 << 62) - 1;
const long double pi = 3.1415926535897932384626433832795;

template <class T> T sqr (T x) {return x * x;}
template <class T> T abs (T x) {return x < 0 ? -x : x;}

const int nmax = 1700;

int px[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
int py[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};

int n, m;
int a[nmax][nmax];
vector<pii> now;

int dfs(int x, int y, int c1, int c2) {
    int res = 1;
    now.pb(mp(x, y));
    a[x][y] = c2;
    forn(i, 9) {
        int nx = x + px[i];
        int ny = y + py[i];
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c1)
            res += dfs(nx, ny, c1, c2);
    }
    return res;
}

int get(int x, int y, int c) {
    int res = 0;
    forn(i, 9) {
        int nx = x + px[i];
        int ny = y + py[i];
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c)
            res ++;
    }
    return res;
}

void write() {
    return;
    forn(i, n) {
        forn(j, m)
            cout << a[i][j];
        cout << endl;
    }
}

int calc() {
    vector<pii> kl, w;
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        int e = get(x, y, 2);
        if (e < 9)
            kl.pb(mp(x, y));
    }
    forn(i, kl.size()) {
        int x = kl[i].fs;
        int y = kl[i].sc;
        a[x][y] = 3;
    }
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        if (a[x][y] == 3) continue;
        int e = get(x, y, 3);
        if (e > 3)
            w.pb(mp(x, y));
    }
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        a[x][y] = 5;
    }
    write();
    int res = 0;
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        if (a[x][y] == 5) {
            int w = dfs(x, y, 5, 6);
            if (w > 6)
                res ++;
        }
    }
    return res;
}

int main ()
{
//  freopen("input.txt", "rt", stdin);
//  freopen("output.txt", "wt", stdout);

    cin >> n >> m;
    forn(i, n)
        forn(j, m) {
            int x;
            scanf("%d", &x);
            a[i][j] = x;
        }
    vector<int> res;
        forn(i, n)
            forn(j, n)
                if (a[i][j] == 1) {
                    now.clear();
                    dfs(i, j, 1, 2);
                    res.pb(calc());
                }
        sort(all(res));
        cout << res.size() << endl;
        forn(i, res.size())
            cout << res[i] << " ";
        cout << endl;
    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <ctime>
#include <cstring>
#include <cassert>
#include <bitset>
#include <sstream>
#include <queue>

using namespace std;

#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define ford(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define fs first
#define sc second
#define last(a) int(a.size() - 1)
#define all(a) a.begin(), a.end()
#define seta(a,x) memset (a, x, sizeof (a))
#define I (int)

typedef long long int64;
typedef pair <int, int> pii;
typedef long double ldb;

const long double eps = 1e-9;
const int inf = (1 << 30) - 1;
const int64 inf64 = ((int64)1 << 62) - 1;
const long double pi = 3.1415926535897932384626433832795;

template <class T> T sqr (T x) {return x * x;}
template <class T> T abs (T x) {return x < 0 ? -x : x;}

const int nmax = 1700;

int px[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
int py[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};

int n, m;
int a[nmax][nmax];
vector<pii> now;

int dfs(int x, int y, int c1, int c2, int d) {
    int res = 1;
    now.pb(mp(x, y));
    a[x][y] = c2;
    for (int i = -d; i <= d; i ++)
    for (int j = -d; j <= d; j ++) {
        int nx = x + i;
        int ny = y + j;
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c1)
            res += dfs(nx, ny, c1, c2, d);
    }
    return res;
}

int get(int x, int y, int c) {
    int res = 0;
    forn(i, 9) {
        int nx = x + px[i];
        int ny = y + py[i];
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c)
            res ++;
    }
    return res;
}

void write() {
    return;
    forn(i, n) {
        forn(j, m)
            cout << a[i][j];
        cout << endl;
    }
}

bool check(int x, int y) {
    int res = 0;
    for (int i = -2; i <= 2; i ++)
    for (int j = -2; j <= 2; j ++) {
        int nx = x + i;
        int ny = y + j;
        if (nx >= 0 && ny >= 0 && nx < n && ny < m) {
            if (a[nx][ny] == 2)
                res --;
            if (a[nx][ny] == 3)
                res ++;
        }
    }
    return res > 0;
}

int calc() {
    vector<pii> kl, w;
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        int e = get(x, y, 2);
        if (e < 9)
            kl.pb(mp(x, y));
    }
    forn(i, kl.size()) {
        int x = kl[i].fs;
        int y = kl[i].sc;
        a[x][y] = 3;
    }
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        if (a[x][y] == 3) continue;
        if (check(x, y))
            w.pb(mp(x, y));
/*      int e = get(x, y, 3);
        int q = get(x, y, 2);
        if (e > 2 && q < 3)
            w.pb(mp(x, y));*/
    }
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        a[x][y] = 5;
    }
    write();
    int res = 0;
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        if (a[x][y] == 5) {
            int w = dfs(x, y, 5, 6, 2);
            if (w > 4)
                res ++;
        }
    }
    return res;
}

int main ()
{
//  freopen("input.txt", "rt", stdin);
//  freopen("output.txt", "wt", stdout);

    cin >> n >> m;
    forn(i, n)
        forn(j, m) {
            int x;
            scanf("%d", &x);
            a[i][j] = x;
        }
    vector<int> res;
        forn(i, n)
            forn(j, n)
                if (a[i][j] == 1) {
                    now.clear();
                    dfs(i, j, 1, 2, 2);
                    res.pb(calc());
                }
        sort(all(res));
        cout << res.size() << endl;
        forn(i, res.size())
            cout << res[i] << " ";
        cout << endl;
    return 0;
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <ctime>
#include <cstring>
#include <cassert>
#include <bitset>
#include <sstream>
#include <queue>

using namespace std;

#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define ford(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define fs first
#define sc second
#define last(a) int(a.size() - 1)
#define all(a) a.begin(), a.end()
#define seta(a,x) memset (a, x, sizeof (a))
#define I (int)

typedef long long int64;
typedef pair <int, int> pii;
typedef long double ldb;

const long double eps = 1e-9;
const int inf = (1 << 30) - 1;
const int64 inf64 = ((int64)1 << 62) - 1;
const long double pi = 3.1415926535897932384626433832795;

template <class T> T sqr (T x) {return x * x;}
template <class T> T abs (T x) {return x < 0 ? -x : x;}

const int nmax = 1700;

int px[] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
int py[] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};

int n, m;
int a[nmax][nmax];
vector<pii> now;

int dfs(int x, int y, int c1, int c2) {
    int res = 1;
    now.pb(mp(x, y));
    a[x][y] = c2;
    forn(i, 9) {
        int nx = x + px[i];
        int ny = y + py[i];
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c1)
            res += dfs(nx, ny, c1, c2);
    }
    return res;
}

int get(int x, int y, int c) {
    int res = 0;
    forn(i, 9) {
        int nx = x + px[i];
        int ny = y + py[i];
        if (nx >= 0 && ny >= 0 && nx < n && ny < m && a[nx][ny] == c)
            res ++;
    }
    return res;
}

void write() {
    return;
    forn(i, n) {
        forn(j, m)
            cout << a[i][j];
        cout << endl;
    }
}

bool check(int x, int y) {
    int res = 0;
    for (int i = -2; i <= 2; i ++)
    for (int j = -2; j <= 2; j ++) {
        int nx = x + i;
        int ny = y + j;
        if (nx >= 0 && ny >= 0 && nx < n && ny < m) {
            if (a[nx][ny] == 2)
                res --;
            if (a[nx][ny] == 3)
                res ++;
        }
    }
    return res > 0;
}

int calc() {
    vector<pii> kl, w;
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        int e = get(x, y, 2);
        if (e < 9)
            kl.pb(mp(x, y));
    }
    forn(i, kl.size()) {
        int x = kl[i].fs;
        int y = kl[i].sc;
        a[x][y] = 3;
    }
    forn(i, now.size()) {
        int x = now[i].fs;
        int y = now[i].sc;
        if (a[x][y] == 3) continue;
        if (check(x, y))
            w.pb(mp(x, y));
/*      int e = get(x, y, 3);
        int q = get(x, y, 2);
        if (e > 2 && q < 3)
            w.pb(mp(x, y));*/
    }
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        a[x][y] = 5;
    }
    write();
    int res = 0;
    forn(i, w.size()) {
        int x = w[i].fs;
        int y = w[i].sc;
        if (a[x][y] == 5) {
            int w = dfs(x, y, 5, 6);
            if (w > 6)
                res ++;
        }
    }
    return res;
}

int main ()
{
//  freopen("input.txt", "rt", stdin);
//  freopen("output.txt", "wt", stdout);

    cin >> n >> m;
    forn(i, n)
        forn(j, m) {
            int x;
            scanf("%d", &x);
            a[i][j] = x;
        }
    vector<int> res;
        forn(i, n)
            forn(j, n)
                if (a[i][j] == 1) {
                    now.clear();
                    dfs(i, j, 1, 2);
                    res.pb(calc());
                }
        sort(all(res));
        cout << res.size() << endl;
        forn(i, res.size())
            cout << res[i] << " ";
        cout << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int x_[4]={0,1,0,-1},y_[4]={1,0,-1,0};
const int N=1616,M=1616,T=10010,D=3,S=(D+D+1)*(D+D+1);
int n,m,a[N][M]={},sum[N][M]={},s[N][M]={},qx[N*M]={},qy[N*M]={};
int ans[N],k=0,root[T]={},tx[T]={},ty[T]={};
int sx,sy,tot,dis[N][M]={},v[N][M]={};
int get_root(int r)
{
	if(r!=root[r])
		root[r]=get_root(root[r]);
	return root[r];
}
int get_sum(int lx,int ly,int rx,int ry)
{
	if(lx<=0 && ly<=0)
		return s[rx][ry];
	if(lx<=0)
		return s[rx][ry]-s[rx][ly-1];
	if(ly<=0)
		return s[rx][ry]-s[lx-1][ry];
	return s[rx][ry]-s[rx][ly-1]-s[lx-1][ry]+s[lx-1][ly-1];
}
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n+D;++i)
		for(int j=1;j<=m+D;++j)
			s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			sum[i][j]=get_sum(i-D,j-D,i+D,j+D);
}
void dfs(int x,int y)
{
	if(sum[x][y]!=S || v[x][y]==1)
		return;
	v[x][y]=1;
	sx+=x,sy+=y;
	++tot;
	for(int d=0;d<4;++d)
		dfs(x+x_[d],y+y_[d]);
}
void bfs(int x,int y)
{
	int head=0,tail=0;
	++tail, qx[tail]=x, qy[tail]=y;
	dis[x][y]=1;
	while(head!=tail)
	{
		++head;
		int sx=qx[head],sy=qy[head];
		for(int d=0;d<4;++d)
		{
			int nx=sx+x_[d],ny=sy+y_[d];
			if(a[nx][ny] && !dis[nx][ny])
			{
				dis[nx][ny]=dis[sx][sy]+1;
				++tail, qx[tail]=nx, qy[tail]=ny;
			}
		}
	}
	int t=0;
	for(int i=1;i<=tail;++i)
	{
		int sx=qx[i],sy=qy[i];
		bool flag=true;
		for(int nx=max(sx-D,0);nx<=sx+D;++nx)
			for(int ny=max(sy-D,0);ny<=sy+D;++ny)
				if(dis[sx][sy]<dis[nx][ny] || sum[nx][ny]==S)
					flag=false;
		if(flag)
			++t,tx[t]=sx,ty[t]=sy;
	}
	for(int i=1;i<=t;++i)
		root[i]=i;
	ans[k]=t;
	//for(int i=1;i<=t;++i)
	//	cerr<<tx[i]<<' '<<ty[i]<<endl;
	//cerr<<endl;
	for(int i=1;i<=t;++i)
		for(int j=i+1;j<=t;++j)
			if(max(abs(tx[i]-tx[j]),abs(ty[i]-ty[j]))<=D)
			{
				int u=get_root(i),v=get_root(j);
				if(u!=v)
					root[u]=v,--ans[k];
			}
}
void calc(int x,int y)
{
	++k;
	sx=sy=tot=0;
	dfs(x,y);
	int hx=sx/tot,hy=sy/tot;
	dis[hx][hy]=0;
	bfs(hx,hy);
}
void work()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(sum[i][j]==S && v[i][j]!=1)
				calc(i,j);
	sort(ans+1,ans+k+1);
	printf("%d\n",k);
	for(int i=1;i<=k;++i)
		printf("%d ",ans[i]);
	printf("\n");
}
int main()
{
	//freopen("F.in","r",stdin);
	//freopen("F.out","w",stdout);
	init();
	work();
}


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <algorithm>

#define mp make_pair

using namespace std;

typedef pair<int, int> PII;

const int MAXN = 2048;

const int dx[] = {0, 0, 1, -1, -1, -1, 1, 1};
const int dy[] = {1, -1, 0, 0, -1, 1, -1, 1};

int h, w;
bool ma3x[MAXN][MAXN];
bool a[MAXN][MAXN], b[MAXN][MAXN];
int num[MAXN][MAXN], color;
queue< PII > q;
vector<int> vec;

void read() {
    scanf("%d %d", &h, &w);
    for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
            scanf("%d", &ma3x[i][j]);
}

bool outside(int x, int y) {
    return (x < 0 || x >= h || y < 0 || y >= w);
}

bool inside(int x, int y) {
    return !outside(x, y);
}

void erose() {
    /// create b
    /// the current picture is a

    memcpy(b, a, sizeof(a));
    for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
            if(b[i][j]) {
                for(int k = 0; k < 8; k ++) {
                    int x = i + dx[k];
                    int y = j + dy[k];

                    if(outside(x, y) || !a[x][y]) {
                        b[i][j] = false;
                        break;
                    }
                }
            }
    memcpy(a, b, sizeof(b));
}

void deviate() {
    /// create b
    /// the current picture is a

    memcpy(b, a, sizeof(a));
    for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
            if(!b[i][j]) {
                for(int k = 0; k < 8; k ++) {
                    int x = i + dx[k];
                    int y = j + dy[k];

                    if(inside(x, y) && a[x][y]) {
                        b[i][j] = true;
                        break;
                    }
                }
            }
    memcpy(a, b, sizeof(b));
}

void bfs1(int x, int y) {
    q.push(mp(x, y));
    num[x][y] = color;
    while(!q.empty()) {
        PII tmp = q.front();
        q.pop();

        for(int i = 0; i < 8; i ++) {
            x = tmp.first + dx[i];
            y = tmp.second + dy[i];

            if(inside(x, y) && a[x][y] && num[x][y] == -1) {
                num[x][y] = color;
                q.push(mp(x, y));
            }
        }
    }
}

void bfs2(int x, int y) {
    q.push(mp(x, y));
    ma3x[x][y] = false;
    int sunNumber = -1;

    while(!q.empty()) {
        PII tmp = q.front();
        q.pop();

        for(int i = 0; i < 8; i ++) {
            x = tmp.first + dx[i];
            y = tmp.second + dy[i];

            if(inside(x, y)) {
                if(num[x][y] != -1) sunNumber = num[x][y];
                else if(ma3x[x][y]) {
                    ma3x[x][y] = false;
                    q.push(mp(x, y));
                }
            }
        }
    }

    if(sunNumber != -1)
        vec[sunNumber] ++;
}

void solve() {
    memcpy(a, ma3x, sizeof(ma3x));
    for(int iter = 0; iter < 3; iter ++)
        erose();
    for(int iter = 0; iter < 5; iter ++)
        deviate();

    memset(num, -1, sizeof(num));

    for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
            if(a[i][j] && num[i][j] == -1) {
                bfs1(i, j);
                color ++;
            }

    vec.resize(color);
    for(int i = 0; i < h; i ++)
        for(int j = 0; j < w; j ++)
            if(ma3x[i][j] && num[i][j] == -1)
                bfs2(i, j);

    sort(vec.begin(), vec.end());

    int cnt = 0;
    for(int i = 0; i < vec.size(); i ++)
        if(vec[i] == 0) break;
        else cnt ++;

    cout << cnt << endl;
    for(int i = 0; i < vec.size(); i ++)
        if(vec[i] == 0) break;
        else {
            if(i) cout << " ";
            cout << vec[i];
        }
    cout << endl;
}

int main()
{
    read();
    solve();

    return 0;
}


// @author peter50216
// #includes {{{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<functional>
#include<math.h>
#include<assert.h>
#include<stdarg.h>
#include<time.h>
#include<limits.h>
#include<ctype.h>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<iostream>
#include<sstream>
using namespace std;
// }}}
// #defines {{{
#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()
#define REP(i,n) for(int i=0;i<(n);i++)
#define REP1(i,a,b) for(int i=(a);i<=(b);i++)
#define REPL(i,x) for(int i=0;x[i];i++)
#define PER(i,n) for(int i=(n)-1;i>=0;i--)
#define PER1(i,a,b) for(int i=(a);i>=(b);i--)
#define RI(x) scanf("%d",&x)
#define DRI(x) int x;RI(x)
#define RII(x,y) scanf("%d%d",&x,&y)
#define DRII(x,y) int x,y;RII(x,y)
#define RIII(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define DRIII(x,y,z) int x,y,z;RIII(x,y,z)
#define RS(x) scanf("%s",x)
#define PI(x) printf("%d\n",x)
#define PIS(x) printf("%d ",x)
#define CASET int ___T,cas=1;scanf("%d ",&___T);while(___T--)
#define CASEN0(n) int cas=1;while(scanf("%d",&n)!=EOF&&n)
#define CASEN(n) int cas=1;while(scanf("%d",&n)!=EOF)
#define MP make_pair
#define PB push_back
#define MS0(x) memset(x,0,sizeof(x))
#define MS1(x) memset(x,-1,sizeof(x))
#define SEP(x) ((x)?'\n':' ')
#define F first
#define S second
#ifdef ONLINE_JUDGE
#define FILEIO(x) freopen(#x ".in","r",stdin);freopen(#x ".out","w",stdout);
#define FILEIOS freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
#else
#define FILEIO(x) ;
#define FILEIOS ;
#endif
typedef pair<int,int> PII;
typedef long long LL;
typedef unsigned long long ULL;
// }}}

int n,m;
int in[1610][1610];
int vis[1610][1610];
vector<PII> all;
int dx[8]={1,1,1,0,-1,-1,-1,0},dy[8]={-1,0,1,1,1,0,-1,-1};
int que[1610*1610][2],qs,qe;
int dis[1610][1610];
inline void bfs(int visid){
    while(qs<qe){
        int x=que[qs][0],y=que[qs][1];
        qs++;
        REP(k,8){
            int xx=x+dx[k],yy=y+dy[k];
            if(xx<0||xx>=n||yy<0||yy>=m||!in[xx][yy]||vis[xx][yy]==visid+1)continue;
            dis[xx][yy]=dis[x][y]+1;
            que[qe][0]=xx;que[qe][1]=yy;vis[xx][yy]=visid+1;qe++;
        }
    }
}
vector<int> ans;
inline void output(){
    REP(i,n){
        REP(j,m)printf("%d ",in[i][j]);puts("");
    }
}
int main(){
    RII(n,m);
    REP(i,n)REP(j,m)RI(in[i][j]);
    REP(i,n)REP(j,m)if(in[i][j]&&!vis[i][j]){
        all.clear();
        qs=qe=0;
        que[qe][0]=i;que[qe][1]=j;vis[i][j]=1;qe++;
        bfs(0);
        REP(k,qe)all.PB(MP(que[k][0],que[k][1]));
        qs=qe=0;
        REP(k,SZ(all)){
            int x=all[k].F,y=all[k].S;
            REP(s,8){
                int xx=x+dx[s],yy=y+dy[s];
                if(xx<0||xx>=n||yy<0||yy>=m||in[xx][yy]==0){
                    que[qe][0]=x;que[qe][1]=y;vis[x][y]=2;dis[x][y]=1;qe++;
                }
            }
        }
        bfs(1);
        qs=qe=0;
        REP(k,SZ(all)){
            int x=all[k].F,y=all[k].S;
            if(dis[x][y]>4){
                //in[x][y]=2;
                que[qe][0]=x;que[qe][1]=y;vis[x][y]=3;dis[x][y]=1;qe++;
            }
        }
        bfs(2);
        int visid=10;
        int cnt=0;
        REP(k,SZ(all)){
            int x=all[k].F,y=all[k].S;
            if(dis[x][y]<=8){
                in[x][y]=0;
            }
        }
        REP(k,SZ(all)){
            int x=all[k].F,y=all[k].S;
            if(in[x][y]&&vis[x][y]==3){
                qs=qe=0;
                que[qe][0]=x;que[qe][1]=y;vis[x][y]=visid+1;qe++;
                bfs(visid);
                visid++;
                cnt++;
            }
        }
        ans.PB(cnt);
    }
    sort(ans.begin(),ans.end());
    PI(SZ(ans));
    REP(i,SZ(ans))printf("%d%c",ans[i],SEP(i==SZ(ans)-1));
}
// vim: fdm=marker:commentstring=\ \"\ %s:nowrap:autoread


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define N1 1610
#define N2 N1*N1
#define len 10
#define cha 4
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[4]={1,-1,0,0},a2[4]={0,0,1,-1};
struct ww {
	int a,b;
} g[N2],h[N2];
int i,j,k,n,m,s,l,r;
int a[N1][N1],f[N1][N1],d[N1][N1],F[N1][N1],ans[N2];
inline void bfs(int x,int y) {
	int i;
	g[l=r=1].a=x,g[1].b=y; f[x][y]=1;
	for (;l<=r;l++) {
		int X=g[l].a,Y=g[l].b;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!f[A][B]) {
				f[A][B]=1; g[++r].a=A,g[r].b=B;
			}
		}
	}
}
inline int cal(int x,int y) {
	int l,r,i;
	h[l=r=1].a=x,h[1].b=y,d[x][y]=0,F[x][y]=1;
	for (;l<=r;l++) {
		int X=h[l].a,Y=h[l].b;
		if (d[X][Y]==d[h[r].a][h[r].b]&&l<=r-cha) break;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!F[A][B]) {
				F[A][B]=1; h[++r].a=A,h[r].b=B;
				d[A][B]=d[X][Y]+1;
			}
		}
	}
	int D=d[h[r].a][h[r].b];
	if (D<=len) For(i,1,r) F[h[i].a][h[i].b]=0;
	return D>len;
}
int main() {
	//freopen("316f.in","r",stdin);
	//freopen("316f.out","w",stdout);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]);
	For(i,1,n)For(j,1,m) if (a[i][j]&&!f[i][j]) {
		bfs(i,j); s=cal(i,j);
		for (k=r;k>1;k--) {
			int A=g[k].a,B=g[k].b;
			if (!F[A][B]) s+=cal(A,B);
		}
		ans[++*ans]=s;
	}
	sort(ans+1,ans+*ans+1);
	printf("%d\n",*ans);
	For(i,1,*ans) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define N1 1610
#define N2 N1*N1
#define len 10
#define cha 4
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[4]={1,-1,0,0},a2[4]={0,0,1,-1};
struct ww {
	int a,b;
} g[N2],h[N2];
int i,j,k,n,m,s,l,r;
int a[N1][N1],f[N1][N1],d[N1][N1],F[N1][N1],ans[N2];
inline void bfs(int x,int y) {
	int i;
	g[l=r=1].a=x,g[1].b=y; f[x][y]=1;
	for (;l<=r;l++) {
		int X=g[l].a,Y=g[l].b;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!f[A][B]) {
				f[A][B]=1; g[++r].a=A,g[r].b=B;
			}
		}
	}
}
inline int cal(int x,int y) {
	int l,r,i;
	h[l=r=1].a=x,h[1].b=y,d[x][y]=0,F[x][y]=1;
	for (;l<=r;l++) {
		int X=h[l].a,Y=h[l].b;
		if (d[X][Y]==d[h[r].a][h[r].b]&&l+cha-1<=r) break;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!F[A][B]) {
				F[A][B]=1; h[++r].a=A,h[r].b=B;
				d[A][B]=d[X][Y]+1;
			}
		}
	}
	int D=d[h[r].a][h[r].b];
	if (D<=len) For(i,1,r) F[h[i].a][h[i].b]=0;
	return D>len;
}
int main() {
	//freopen("316f.in","r",stdin);
	//freopen("316f.out","w",stdout);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]);
	For(i,1,n)For(j,1,m) if (a[i][j]&&!f[i][j]) {
		bfs(i,j); s=cal(i,j);
		for (k=r;k>1;k--) {
			int A=g[k].a,B=g[k].b;
			if (!F[A][B]) s+=cal(A,B);
		}
		ans[++*ans]=s;
	}
	sort(ans+1,ans+*ans+1);
	printf("%d\n",*ans);
	For(i,1,*ans) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define N1 1610
#define N2 N1*N1
#define len 10
#define cha 4
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[4]={1,-1,0,0},a2[4]={0,0,1,-1};
struct ww {
	int a,b;
} g[N2],h[N2];
int i,j,k,n,m,s,l,r;
int a[N1][N1],f[N1][N1],d[N1][N1],F[N1][N1],ans[N2];
inline void bfs(int x,int y) {
	int i;
	g[l=r=1].a=x,g[1].b=y; f[x][y]=1;
	for (;l<=r;l++) {
		int X=g[l].a,Y=g[l].b;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!f[A][B]) {
				f[A][B]=1; g[++r].a=A,g[r].b=B;
			}
		}
	}
}
inline int cal(int x,int y) {
	int l,r,i;
	h[l=r=1].a=x,h[1].b=y,d[x][y]=0,F[x][y]=1;
	for (;l<=r;l++) {
		int X=h[l].a,Y=h[l].b;
		if (d[X][Y]==d[h[r].a][h[r].b]&&l<r-cha) break;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!F[A][B]) {
				F[A][B]=1; h[++r].a=A,h[r].b=B;
				d[A][B]=d[X][Y]+1;
			}
		}
	}
	int D=d[h[r].a][h[r].b];
	if (D<=len) For(i,1,r) F[h[i].a][h[i].b]=0;
	return D>len;
}
int main() {
	//freopen("316f.in","r",stdin);
	//freopen("316f.out","w",stdout);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]);
	For(i,1,n)For(j,1,m) if (a[i][j]&&!f[i][j]) {
		bfs(i,j); s=cal(i,j);
		for (k=r;k>1;k--) {
			int A=g[k].a,B=g[k].b;
			if (!F[A][B]) s+=cal(A,B);
		}
		ans[++*ans]=s;
	}
	sort(ans+1,ans+*ans+1);
	printf("%d\n",*ans);
	For(i,1,*ans) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define N1 1610
#define N2 N1*N1
#define len 10
#define cha 4
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
const int a1[4]={1,-1,0,0},a2[4]={0,0,1,-1};
struct ww {
	int a,b;
} g[N2],h[N2];
int i,j,k,n,m,s,l,r;
int a[N1][N1],f[N1][N1],d[N1][N1],F[N1][N1],ans[N2];
inline void bfs(int x,int y) {
	int i;
	g[l=r=1].a=x,g[1].b=y; f[x][y]=1;
	for (;l<=r;l++) {
		int X=g[l].a,Y=g[l].b;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!f[A][B]) {
				f[A][B]=1; g[++r].a=A,g[r].b=B;
			}
		}
	}
}
inline int cal(int x,int y) {
	int l,r,i;
	h[l=r=1].a=x,h[1].b=y,d[x][y]=0,F[x][y]=1;
	for (;l<=r;l++) {
		int X=h[l].a,Y=h[l].b;
		if (d[X][Y]==d[h[r].a][h[r].b]&&l=<r-cha) break;
		For(i,0,3) {
			int A=X+a1[i],B=Y+a2[i];
			if (a[A][B]&&!F[A][B]) {
				F[A][B]=1; h[++r].a=A,h[r].b=B;
				d[A][B]=d[X][Y]+1;
			}
		}
	}
	int D=d[h[r].a][h[r].b];
	if (D<=len) For(i,1,r) F[h[i].a][h[i].b]=0;
	return D>len;
}
int main() {
	//freopen("316f.in","r",stdin);
	//freopen("316f.out","w",stdout);
	scanf("%d%d",&n,&m);
	For(i,1,n)For(j,1,m) scanf("%d",&a[i][j]);
	For(i,1,n)For(j,1,m) if (a[i][j]&&!f[i][j]) {
		bfs(i,j); s=cal(i,j);
		for (k=r;k>1;k--) {
			int A=g[k].a,B=g[k].b;
			if (!F[A][B]) s+=cal(A,B);
		}
		ans[++*ans]=s;
	}
	sort(ans+1,ans+*ans+1);
	printf("%d\n",*ans);
	For(i,1,*ans) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, counth, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
LLD tot_x, tot_y;
int cx, cy;

int heavy(int x, int y){
	FOE(dx,-5,7) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) return 0;
		if (a[ti][tj] == 0) return 0;
	}
	return 1;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	if (heavy(x, y)){
		tot_x += x;
		tot_y += y;
		++counth;
	}
	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-2,3) FOR(j,-2,3){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = tot_x = tot_y = 0;
		counth = 0;
		dfs(i, j);
		cx = tot_x / counth;
		cy = tot_y / counth;
		double r = round(sqrt(area * 1. / acos(-1.0)));
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}

/*	FOR(i,0,n){
		FOR(j,0,m) printf("%d",a[i][j]);
		puts("");
	}
	*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
double tot_x, tot_y, total;
int cx, cy, A;

double Weight(int x, int y){
	int ok = 1;
	double res = 0;
	FOE(dx,-3,3) FOE(dy,-3,3){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.3;
	ok = 1;
	FOE(dx,-5,5) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.7;
	return res;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	double w = Weight(x, y);
	tot_x += x * w;
	tot_y += y * w;
	total += w;
	if (w > 0.1) ++A;

	++area;
	FOR(i,-1,2) FOR(j,-1,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-1,2) FOR(j,-1,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = 0;
		tot_x = tot_y = 0;
		total = 0;
		A = 0;
		dfs(i, j);
		cx = (int)(tot_x / total);
		cy = (int)(tot_y / total);
		double r = round(sqrt(A * 1. / acos(-1.0))) + 8.0;
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}
/*
	FOR(i,0,n){
		FOR(j,0,m) printf("%d ", a[i][j]);
		puts("");
	}
*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
double tot_x, tot_y, total;
int cx, cy, A;

double Weight(int x, int y){
	int ok = 1;
	double res = 0;
	FOE(dx,-3,3) FOE(dy,-3,3){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.3;
	ok = 1;
	FOE(dx,-5,5) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.7;
	return res;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	double w = Weight(x, y);
	tot_x += x * w;
	tot_y += y * w;
	total += w;
	if (w > 0.1) ++A;

	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-2,3) FOR(j,-2,3){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = 0;
		tot_x = tot_y = 0;
		total = 0;
		A = 0;
		dfs(i, j);
		cx = (int)(tot_x / total);
		cy = (int)(tot_y / total);
		double r = round(sqrt(A * 1. / acos(-1.0))) + 5.0;
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}
/*
	FOR(i,0,n){
		FOR(j,0,m) printf("%d ", a[i][j]);
		puts("");
	}
*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
LLD tot_x, tot_y;
int cx, cy;

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;
	tot_x += x;
	tot_y += y;
	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-2,3) FOR(j,-2,3){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = tot_x = tot_y = 0;
		dfs(i, j);
		cx = tot_x / area;
		cy = tot_y / area;
		double r = round(sqrt(area * 1. / acos(-1.0)));
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}

/*	FOR(i,0,n){
		FOR(j,0,m) printf("%d",a[i][j]);
		puts("");
	}
	*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, counth, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
LLD tot_x, tot_y;
int cx, cy;

int heavy(int x, int y){
	FOE(dx,-5,5) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) continue;
		if (a[ti][tj] == 0) return 0;
	}
	return 1;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	if (heavy(x, y)){
		tot_x += x;
		tot_y += y;
		++counth;
	}
	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-2,3) FOR(j,-2,3){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = tot_x = tot_y = 0;
		counth = 0;
		dfs(i, j);
		cx = tot_x / counth;
		cy = tot_y / counth;
		double r = round(sqrt(area * 1. / acos(-1.0)));
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}

/*	FOR(i,0,n){
		FOR(j,0,m) printf("%d",a[i][j]);
		puts("");
	}
	*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
double tot_x, tot_y, total;
int cx, cy, A;

double Weight(int x, int y){
	int ok = 1;
	double res = 0;
	FOE(dx,-3,3) FOE(dy,-3,3){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.3;
	ok = 1;
	FOE(dx,-5,5) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.7;
	return res;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	double w = Weight(x, y);
	tot_x += x * w;
	tot_y += y * w;
	total += w;
	if (w > 0.1) ++A;

	++area;
	FOR(i,-1,2) FOR(j,-1,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-1,2) FOR(j,-1,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = 0;
		tot_x = tot_y = 0;
		total = 0;
		A = 0;
		dfs(i, j);
		cx = (int)(tot_x / total);
		cy = (int)(tot_y / total);
		double r = round(sqrt(A * 1. / acos(-1.0))) + 5.0;
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}
/*
	FOR(i,0,n){
		FOR(j,0,m) printf("%d ", a[i][j]);
		puts("");
	}
*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
LLD tot_x, tot_y;
int cx, cy;

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;
	tot_x += x;
	tot_y += y;
	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = tot_x = tot_y = 0;
		dfs(i, j);
		cx = tot_x / area;
		cy = tot_y / area;
		double r = round(sqrt(area * 1. / acos(-1.0)));
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}

/*	FOR(i,0,n){
		FOR(j,0,m) printf("%d",a[i][j]);
		puts("");
	}
	*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define FOR(i,s,e) for (int i=(s); i<(e); i++)
#define FOE(i,s,e) for (int i=(s); i<=(e); i++)
#define FOD(i,s,e) for (int i=(s)-1; i>=(e); i--)
#define CLR(a,x) memset(a, x, sizeof(a))
#define EXP(i,l) for (int i=(l); i; i=qn[i])
#define N 1700
#define LLD long long int
using namespace std;

int n, m, cnt, ray, area = 0;
int a[N][N], res[100000];
bool v[N][N], u[N][N];
int lx[N*N], ly[N*N];
double tot_x, tot_y, total;
int cx, cy;

double Weight(int x, int y){
	int ok = 1;
	double res = 0;
	FOE(dx,-3,3) FOE(dy,-3,3){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.3;
	ok = 1;
	FOE(dx,-5,5) FOE(dy,-5,5){
		int ti = x + dx, tj = y + dy;
		if (ti < 1 || tj < 1 || ti >= n || tj >= m) ok = 0;
		if (a[ti][tj] == 0) ok = 0;
	}
	if (ok) res += 0.7;
	return res;
}

void dfs(int x, int y){
	v[x][y] = 1;
	lx[area] = x, ly[area] = y;

	double w = Weight(x, y);
	tot_x += x * w;
	tot_y += y * w;
	total += w;

	++area;
	FOR(i,-1,2) FOR(j,-2,2){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !v[ti][tj]) dfs(ti, tj);
	}
}

void dfs2(int x, int y){
	u[x][y] = 1;
	FOR(i,-2,3) FOR(j,-2,3){
		int ti = x + i, tj = y + j;
		if (a[ti][tj] == 1 && !u[ti][tj]) dfs2(ti, tj);
	}
}

double dist(int x, int y, int a, int b){
	return sqrt((x - a) * (x - a) + (y - b) * (y - b) + 0.0);
}

int main(){
	scanf("%d%d", &n, &m), ++n, ++m;
	FOR(i,1,n) FOR(j,1,m) scanf("%d", &a[i][j]);
	FOR(i,0,n) FOR(j,0,m) if (a[i][j] == 1 && !v[i][j]){
		area = 0;
		tot_x = tot_y = 0;
		total = 0;
		dfs(i, j);
		cx = (int)(tot_x / total);
		cy = (int)(tot_y / total);
		double r = round(sqrt(area * 1. / acos(-1.0)));
		FOR(k,0,area) if (dist(lx[k], ly[k], cx, cy) <= r) a[lx[k]][ly[k]] = 2;
	//	printf("%d %d %d %f\n", area, cx, cy, r);
		int ray = 0;
	    FOR(k,0,area){
			int x, y;
			x = lx[k], y = ly[k];
			if (a[x][y] == 1 && !u[x][y]){
				dfs2(x, y);
				++ray;
			}
		}
		res[cnt] = ray;
		++cnt;
	}

/*	FOR(i,0,n){
		FOR(j,0,m) printf("%d",a[i][j]);
		puts("");
	}
	*/
	printf("%d\n", cnt);
	sort(res, res + cnt);
	FOR(i,0,cnt) printf("%d ", res[i]);
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 5e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 8);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 6e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 5);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 6e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 7);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 3e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 9);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 6e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 9);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 5e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 8);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 6e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 8);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[] = {0, -1, 0, 1, -1, 1, -1, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 6e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	int n = 0;
	for (int i = 0; i < 8; ++i) {
		int nx = x + dx[i], ny = y + dy[i];
		if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
			++n;
		}
	}
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 5) && n <= 3;
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[] = {0, -1, 0, 1, -1, 1, -1, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 1e-1;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	int n = 0;
	for (int i = 0; i < 8; ++i) {
		int nx = x + dx[i], ny = y + dy[i];
		if (nx >= 0 && ny >= 0 && col[nx][ny] == 1) {
			++n;
		}
	}
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 4) && n <= 3;
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 3e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 9);
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;

typedef pair<int,int> pii;

const double kPi = acos(-1.0);

int dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[] = {0, -1, 0, 1, -1, 1, -1, 1};

int col[1700][1700];
char was[1700][1700];
vector<int> answer;

double kEps = 5e-2;

double Sqr(double x) {
	return x * x;
}

bool IsRay(double x, double y, double cx, double cy, double sx, double sy) {
//			cerr << x << " " << y << endl;
	int n = 0;
	for (int i = 0; i < 8; ++i) {
		int nx = x + dx[i], ny = y + dy[i];
		if (nx >= 0 && ny >= 0 && col[nx][ny] == 1) {
			++n;
		}
	}
	return Sqr(x - cx) + Sqr(y - cy) > Sqr(sx + 5) && n <= 3;
}

int Solve (int x, int y) {
	double sx = 0, sy = 0;
	int q = 0;
	queue<pii> Q;
	Q.push(pii(x, y));
	was[x][y] = 1;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		++q;
		int x = cur.first, y = cur.second;
		sx += x;
		sy += y;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 1) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 1;
		}
	}
	double cx = sx / q, cy = sy / q;
	cerr << cx << " " << cy << endl;
	sy = 0;
	sx = 1000000;
	int qq = 0;
	Q.push(pii(x, y));
	was[x][y] = 2;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		bool side = false;
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0) {
				side = true;
			}
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 2) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 2;
		}
		if (side) {
			sx = min(sx, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			sy = max(sy, sqrt((cx - x) * (cx - x) + (cy - y) * (cy - y)));
			//sx += (cx - x) * (cx - x);
			//sy += (cy - y) * (cy - y);
			//++qq;
		}
	}
	//sx = sqrt(sx / q);
	//sy = sqrt(sy / q);
//	cerr << q << " " << qq << endl;

	cerr << sx << " " << sy << endl;

	vector<double> angles;
	Q.push(pii(x, y));
	was[x][y] = 10;
	while (!Q.empty()) {
		pii cur = Q.front();
		Q.pop();
		int x = cur.first, y = cur.second;
		if (IsRay(x, y, cx, cy, sx, sy)) {
			angles.push_back(atan2(y - cy, x - cx));
		}
		for (int i = 0; i < 4; ++i) {
			int nx = x + dx[i], ny = y + dy[i];
			if (nx < 0 || ny < 0 || col[nx][ny] == 0 || was[nx][ny] == 10) {
				continue;
			}
			Q.push(pii(nx, ny));
			was[nx][ny] = 10;
		}
	}

	cerr << angles.size() << endl;

	int ret = 0;
	sort(angles.begin(), angles.end());
	if (angles.empty()) {
		return 0;
	}
	if (angles.size() == 1) {
		return 1;
	}
	ret = 1;
	for (int i = 1; i < angles.size(); ++i) {
		if (angles[i] - angles[i - 1] > kEps) {
			++ret;
		}
	}
	if (angles[0] - angles.back() + 2 * kPi < kEps) {
		--ret;
	}
	return ret;
}

int main() {
//	freopen("d.in", "r", stdin);
	int n, m;
	cin >> n >> m;
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> col[i][j];
		}
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (col[i][j] == 1 && !was[i][j]) {
				answer.push_back(Solve(i, j));
			}
		}
	}
	sort(answer.begin(), answer.end());
	cout << answer.size() << endl;
	for (int i = 0; i < answer.size(); ++i) {
		cout << answer[i] << " ";
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
typedef pair<int,int> pii;
const int MN=2000;
bool mp[MN][MN];
int mark[MN][MN];
bool good[MN][MN];
int n,m;
vector <pii> all;
vector <int> rays;
int cc=0;
bool isg(int x,int y)
{
	int cnt=0;
	for (int i=x-2; i<=x+2; i++)
	{
	    for (int j=y-2; j<=y+2; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==1) cnt++;
		}
	}
	return cnt<=11;
}
void dfs1(int x,int y)
{
	mark[x][y]=1;
	all.push_back(pii(x,y));
	for (int i=x-1; i<=x+1; i++)
	{
	    for (int j=y-1; j<=y+1; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==0) dfs1(i,j);
		}
	}
}
void dfs2(int x,int y)
{
	mark[x][y]=2;
	cc++;
	for (int i=x-1; i<=x+1; i++)
	{
	    for (int j=y-1; j<=y+1; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==1 && good[i][j]) dfs2(i,j);
		}
	}
}
int main()
{
	cin >>n >>m;
	for (int i=0; i<n; i++) for (int j=0; j<m; j++) cin>>mp[i][j];
	for (int i=0; i<n; i++)
	{
	    for (int j=0; j<m; j++)
		{
		    if (mark[i][j]==0 && mp[i][j]==1)
	        {
		        int cnt=0;
		        all.clear();
		        dfs1(i,j);
		        for (int k=0; k<all.size(); k++)
		        {
			        int x=all[k].first,y=all[k].second;
			        good[x][y]=isg(x,y);
		        }
		        for (int k=0; k<all.size(); k++) if (good[all[k].first][all[k].second] && mark[all[k].first][all[k].second]==1)
		        {
			        cc=0;
			        dfs2(all[k].first,all[k].second);
			        if (cc>=3) cnt++;
		        }
		        for (int k=0; k<all.size(); k++) mark[all[k].first][all[k].second]=3;
		        rays.push_back(cnt);
	        }
	    }
	}
	sort(rays.begin(),rays.end());
	cout <<rays.size() <<endl;
	for (int i=0; i<rays.size(); i++) cout <<rays[i] <<" ";
	cout <<endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
typedef pair<int,int> pii;
const int MN=2000;
bool mp[MN][MN];
int mark[MN][MN];
bool good[MN][MN];
int n,m;
vector <pii> all;
vector <int> rays;
int cc=0;
bool isg(int x,int y)
{
	int cnt=0;
	for (int i=x-2; i<=x+2; i++)
	{
	    for (int j=y-2; j<=y+2; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==1) cnt++;
		}
	}
	return cnt<=11;
}
void dfs1(int x,int y)
{
	mark[x][y]=1;
	all.push_back(pii(x,y));
	for (int i=x-1; i<=x+1; i++)
	{
	    for (int j=y-1; j<=y+1; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==0) dfs1(i,j);
		}
	}
}
void dfs2(int x,int y)
{
	mark[x][y]=2;
	cc++;
	for (int i=x-1; i<=x+1; i++)
	{
	    for (int j=y-1; j<=y+1; j++)
		{
		    if (i>=0 && j>=0 && i<n && j<m && mp[i][j] && mark[i][j]==1 && good[i][j]) dfs2(i,j);
		}
	}
}
int main()
{
	cin >>n >>m;
	for (int i=0; i<n; i++) for (int j=0; j<m; j++) cin>>mp[i][j];
	for (int i=0; i<n; i++)
	{
	    for (int j=0; j<m; j++)
		{
		    if (mark[i][j]==0 && mp[i][j]==1)
	        {
		        int cnt=0;
		        all.clear();
		        dfs1(i,j);
		        for (int k=0; k<all.size(); k++)
		        {
			        int x=all[k].first,y=all[k].second;
			        good[x][y]=isg(x,y);
		        }
		        for (int k=0; k<all.size(); k++) if (good[all[k].first][all[k].second] && mark[all[k].first][all[k].second]==1)
		        {
			        cc=0;
			        dfs2(all[k].first,all[k].second);
			        if (cc>=2) cnt++;
		        }
		        for (int k=0; k<all.size(); k++) mark[all[k].first][all[k].second]=3;
		        rays.push_back(cnt);
	        }
	    }
	}
	sort(rays.begin(),rays.end());
	cout <<rays.size() <<endl;
	for (int i=0; i<rays.size(); i++) cout <<rays[i] <<" ";
	cout <<endl;
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<bool> > pic, ray, vis;
vector<int> ans;
int cnt;

void floodfill(int x, int y)
{
	if (vis[x][y] || !pic[x][y]) return;
	vis[x][y] = true;
	if (!pic[x-2][y] && !pic[x+2][y]) {
		if (!pic[x][y-1] && (!pic[x-2][y+5] || !pic[x+2][y+5])) ray[x][y] = true;
		if (!pic[x][y+1] && (!pic[x-2][y-5] || !pic[x+2][y-5])) ray[x][y] = true;
	}
	if (!pic[x][y-2] && !pic[x][y+2]) {
		if (!pic[x-1][y] && (!pic[x+5][y-2] || !pic[x+5][y+2])) ray[x][y] = true;
		if (!pic[x+1][y] && (!pic[x-5][y-2] || !pic[x-5][y+2])) ray[x][y] = true;
	}
	if (ray[x][y] && !ray[x-1][y-1] && !ray[x-1][y+1] && !ray[x+1][y-1] && !ray[x+1][y+1]) ++cnt;
	floodfill(x-1,y);
	floodfill(x+1,y);
	floodfill(x,y-1);
	floodfill(x,y+1);
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	int n, m;
	cin >> n >> m;
	pic = ray = vis = vector<vector<bool> >(n+4, vector<bool>(m+4));
	char c;
	n++, m++;
	for (int i = 2; i <= n; ++i) {
		for (int j = 2; j <= m; ++j) {
			cin >> c;
			pic[i][j] = (c == '1');
		}
	}

	for (int i = 2; i <= n; ++i) {
		for (int j = 2; j <= m; ++j) {
			if (pic[i][j] && !vis[i][j])	{
				cnt = 0;
				floodfill(i,j);
				ans.push_back(cnt);
				cout << endl;
			}
		}
	}

	sort(ans.begin(), ans.end());
	cout << ans.size() << '\n';
	for (vector<int>::iterator it = ans.begin(); it != ans.end(); ++it)
		cout << *it << ' ';
	return 0;
}


#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <set>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm>
#include <memory.h>
#include <string>
#include <sstream>

using namespace std;

const int dx[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const int dy[8] = {1, 0, -1, 0, 1, -1, 1, -1};

int a[1620][1620];
int x[1620*1620], y[1620*1620];
bool was[1620][1620];
int cc[1620][1620];
bool end[1620][1620];
int s[1620*1620];
int px[1620][1620], py[1620][1620];
int lx[1620], ly[1620];

int main() {
  int h, w;
  scanf("%d %d", &h, &w);
  for (int i=0;i<h;i++)
    for (int j=0;j<w;j++) scanf("%d", &a[i][j]);
  for (int i=0;i<h;i++)
    for (int j=0;j<w;j++) end[i][j] = 0;
  for (int i=0;i<h;i++) {
    for (int j=0;j<w;j++) {
      if (a[i][j] == 1) {
        int cnt = 0;
        for (int x=i-5;x<=i+5;x++)
          for (int y=j-5;y<=j+5;y++)
            if (x >= 0 && y >= 0 && x < h && y < w && a[x][y]) cnt++;
        cc[i][j] = cnt;
      }
//      printf("%03d ", cc[i][j]);
      }
//      printf("\n");
      }
  for (int i=0;i<=255;i++) lx[i] = ly[i] = -1;
  for (int i=0;i<h;i++)
    for (int j=0;j<w;j++)
      if (a[i][j]) {
        was[i][j] = false;
        px[i][j] = lx[cc[i][j]];
        py[i][j] = ly[cc[i][j]];
        lx[cc[i][j]] = i;
        ly[cc[i][j]] = j;
      }
  for (int val=1;val<35;val++) {
    int xx = lx[val], yy = ly[val];
    while (xx >= 0 || yy >= 0) {
      if (!was[xx][yy]) {
        end[xx][yy] = true;
        int i = 1, e = 1;
        x[1] = xx; y[1] = yy;
        was[xx][yy] = true;
        while (i <= e) {
          for (int j=0;j<4;j++) {
            int xk = x[i]+dx[j];
            int yk = y[i]+dy[j];
            if (xk >= 0 && yk >= 0 && xk < h && yk < w)
              if (a[xk][yk] && !was[xk][yk] && cc[xk][yk] < 63) {
                e++;
                x[e] = xk;
                y[e] = yk;
                was[xk][yk] = true;
              }
          }
          i++;
        }
      }
      int nx = px[xx][yy];
      int ny = py[xx][yy];
      xx = nx; yy = ny;
    }
  }
  int ks = 0;
  for (int ii=0;ii<h;ii++)
    for (int jj=0;jj<w;jj++)
      if (a[ii][jj]) {
        int i = 1, e = 1;
        x[1] = ii; y[1] = jj;
        a[ii][jj] = 0;
        int cnt = (end[ii][jj]);
        while (i <= e) {
          for (int j=0;j<8;j++) {
            int xk = x[i]+dx[j];
            int yk = y[i]+dy[j];
            if (xk >= 0 && yk >= 0 && xk < h && yk < w)
              if (a[xk][yk]) {
                e++;
                x[e] = xk;
                y[e] = yk;
                a[xk][yk] = 0;
                if (end[xk][yk]) cnt++;
              }
          }
          i++;
        }
        s[ks++] = cnt;
      }
  sort(s, s+ks);
  printf("%d\n", ks);
  for (int i=0;i<ks-1;i++) printf("%d ", s[i]);
  if (ks > 0) printf("%d", s[ks-1]);
  printf("\n");
  return 0;
}


#pragma comment(linker, "/STACK:128777216")

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <vector>
#include <deque>
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <functional>
#include <numeric>
#include <sstream>
#include <exception>
#include <cassert>

typedef long long i64;
typedef unsigned int u32;
const int null = 0;

using namespace std;

template<class T> int size(const T &a) {
	return int(a.size());
}
template<class T> T abs(const T &a) {
	return (a < 0? -a: a);
}
template<class T> T sqr(const T &a) {
	return a * a;
}

#define all(a) a.begin(),a.end()

const int max_n = 2001;

int a[max_n][max_n];
typedef bool bool2d[max_n][max_n];
bool2d was, was2, was3;
int n, m;

struct Pos {
	int r, c;
	void init(int r, int c) {
		this->r = r;
		this->c = c;
	}
} q[max_n * max_n], q1[max_n * max_n], q2[max_n * max_n];

void bfs(int i, int j, Pos* q, bool2d &was, int &u) {
	q[0].init(i, j);
	was[i][j] = true;
	u = 1;
	for (int d = 0; d < u; d++) {
		int i = q[d].r, j = q[d].c;
		for (int di = -1; di <= 1; di++) {
			for (int dj = -1; dj <= 1; dj++) {
				int r = i + di, c = j + dj;
				if (r >= 0 && c >= 0 && r < n && c < m) {
					if (!was[r][c]) {
						q[u++].init(r, c);
						was[r][c] = true;
					}
				}
			}
		}
	}
}

int bfs2(int i, int j, int dist) {
	q2[0].init(i, j);
	was2[i][j] = true;
	int u = 1;
	for (int i = 0, d = 0; i < dist; i++) {
		int cu = u;
		for (; d < cu; d++) {
			int i = q2[d].r, j = q2[d].c;
			for (int di = -1; di <= 1; di++) {
				for (int dj = -1; dj <= 1; dj++) {
					int r = i + di, c = j + dj;
					if (r >= 0 && c >= 0 && r < n && c < m) {
						if (!was2[r][c]) {
							if (u == 90) {
								for (int i = 0; i < u; i++) {
									was2[q2[i].r][q2[i].c] = false;
								}
								return 1;
							}
							q2[u++].init(r, c);
							was2[r][c] = true;
						}
					}
				}
			}
		}
	}
	for (int i = 0; i < u; i++) {
		was2[q2[i].r][q2[i].c] = false;
	}
	return 0;
}

vector<int> res;

int main() {
#ifdef pperm
	freopen("input.txt", "r", stdin);
	//freopen("input.txt", "w", stdout);
	//freopen("output.txt", "w", stdout);
#endif
	scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			scanf("%d", &a[i][j]);
			if (!a[i][j]) {
				was[i][j] = was2[i][j] = was3[i][j] = true;
			}
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			if (a[i][j] && !was[i][j]) {
				int u;
				bfs(i , j, q, was, u);
				for (int i = 0; i < u; i++) {
					int r = q[i].r, c = q[i].c;
					if (bfs2(r, c, 10)) {
						was3[r][c] = true;
					}
				}
				int cur = 0;
				for (int i = 0; i < u; i++) {
					int r = q[i].r, c = q[i].c;
					if (!was3[r][c]) {
						int q = 0;
						bfs(r, c, q1, was3, q);
						cur++;
					}
				}
				res.push_back(cur);
			}
		}
	}
	printf("%d\n", res.size());
	sort(all(res));
	for (int i = 0; i < res.size(); i++) {
		printf("%d ", res[i]);
	}
#ifdef pperm
	fprintf(stderr, "\n%.3lf\n", clock() / double(CLOCKS_PER_SEC));
#endif
	return 0;
}