/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 23时27分38秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= m; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        for (int i = 2; i <= m; ++i) {
            if (a[i].size() < k) {
                for (int j = 0; j < a[i].size(); ++j)
                    v.push_back(a[i][j]);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need && i < v.size(); ++i)
                cost += v[i];
        }
        min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 23时34分15秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 100000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= m; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        for (int i = 2; i <= m; ++i) {
            if (a[i].empty())
                continue;
            if (a[i].size() < k) {
                for (int j = 0; j < a[i].size(); ++j)
                    v.push_back(a[i][j]);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need && i < v.size(); ++i)
                cost += v[i];
        }
        if (need <= v.size())
            min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 23时31分46秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 100000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= m; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        for (int i = 2; i <= m; ++i) {
            if (a[i].empty())
                continue;
            if (a[i].size() < k) {
                for (int j = 0; j < a[i].size(); ++j)
                    v.push_back(a[i][j]);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need && i < v.size(); ++i)
                cost += v[i];
        }
        min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 23时19分32秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= m; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        v.reserve(n);
        for (int i = 2; i <= m; ++i) {
            if (a[i].size() < k) {
                for (int j = 0; j < a[i].size(); ++j)
                    v.push_back(a[i][j]);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need; ++i)
                cost += v[i];
        }
        min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 23时16分51秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= m; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        v.reserve(n);
        for (int i = 2; i <= m; ++i) {
            if (a[i].size() < k) {
                for (int j = 0; j < a[i].size(); ++j)
                    v.push_back(a[i][j]);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > v.size())
            break;
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need; ++i)
                cost += v[i];
        }
        min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 22时52分17秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= n; ++i)
        sort(a[i].begin(), a[i].end());

    int min_cost = INF;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size(), cost = 0;
        vector<int> v;
        v.reserve(n);
        for (int i = 2; i <= n; ++i) {
            if (a[i].size() < k) {
                for (int &x: a[i])
                    v.push_back(x);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need && i < v.size(); ++i)
                cost += v[i];
        }
        if (need <= v.size())
            min_cost = min(min_cost, cost);
    }
    printf("%d\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 22时47分07秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= n; ++i)
        sort(a[i].begin(), a[i].end());

    int min_cost = INF;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size(), cost = 0;
        vector<int> v;
        v.reserve(n);
        for (int i = 2; i <= n; ++i) {
            if (a[i].size() < k) {
                for (int &x: a[i])
                    v.push_back(x);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need; ++i)
                cost += v[i];
        }
        min_cost = min(min_cost, cost);
    }
    printf("%d\n", min_cost);

    return 0;
}


/************************************************************************
* File Name : cf1020C.cpp
* Purpose : water?
* Creation Date : 2018年08月11日
* Last Modified : 2018年08月11日 星期六 22时56分11秒
* Created By : hi@goushi.me
************************************************************************/
#include <bits/stdc++.h>
using namespace std;

// const
const int N = 10000 + 10;
const int INF = 0x3f3f3f3f;
const int _INF = (int)0x80000000;
const int MOD = 1000000000 + 7;
const double EPS = 1E-8;

// long long
typedef long long LL;
#ifdef _WIN32
#define lld I64d
#endif

// vector
typedef vector<int> VI;
#define pb push_back
#define all(x) (x).begin(), (x).end()
#define sz(x) ((int)(x).size())

// pair
typedef pair<int, int> PII;
#define mp make_pair
#define fi first
#define se second

#define mst(a,x) memset(a,x,sizeof(a))

int p[N], c[N];
vector<int> a[N];

int main() {
#ifdef LOCAL
    freopen("in", "r", stdin);
#endif

    LL sum = 0;
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &p[i], &c[i]);
        sum += c[i];
        a[p[i]].push_back(c[i]);
    }

    for (int i = 1; i <= n; ++i)
        sort(a[i].begin(), a[i].end());

    LL min_cost = sum;
    for (int k = a[1].size(); k <= n; ++k) {
        int need = k - a[1].size();
        LL cost = 0;
        vector<int> v;
        v.reserve(n);
        for (int i = 2; i <= n; ++i) {
            if (a[i].size() < k) {
                for (int &x: a[i])
                    v.push_back(x);
            } else {
                for (int j = 0; j < a[i].size() - k + 1; ++j) {
                    cost += a[i][j];
                    --need;
                }
            }
        }
        if (need > 0) {
            sort(v.begin(), v.end());
            for (int i = 0; i < need && i < v.size(); ++i)
                cost += v[i];
        }
        if (need <= v.size())
            min_cost = min(min_cost, cost);
    }
    printf("%lld\n", min_cost);

    return 0;
}


#include <bits/stdc++.h>
#define inf 1e18
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3001],t1,t2,tmax;
struct ugh{
	LL c,t;
	LL id;
	bool u;
};
vector <ugh> x,w;
LL ans;
bool done(){
	for (int i=2;i<=m;i++)
	if (cnt[i]>=cnt[1])
	return false;
	return true;
}
bool cmp(ugh A,ugh B){
	if (A.c!=B.c)
		return A.c<B.c;
	return cnt[A.t]>cnt[B.t];
}
int main(){
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1){
			ugh tmp = {t2,t1,false};
			x.pb(tmp);
		}
	}
	ans=0;
	sort(x.begin(),x.end(),cmp);
	for (int i=0;i<(int)x.size();i++)
	x[i].id=i;
	while (!done()){
		//cout<<ans<<"\n";
		//find max vote
		LL tmax=-1;
		w.clear();
		for (int i=2;i<=n;i++)
		if (cnt[i]>tmax)
			tmax=cnt[i];
		//find max vote min cost
		LL minc=inf;
		ugh tmpmin;
		for(int i=0;i<(int)x.size();i++)
		if (!x[i].u){//each voter
			if (cnt[x[i].t]==tmax){
				if (x[i].c<minc){
					minc=x[i].c;
					tmpmin=x[i];
				}
			}
			else if (w.size()<3){
				w.pb(x[i]);
			}
		}
		//find not max vote but min cost *3
		if (cnt[1]-1==tmax){
				if (w.size()<2 || tmpmin.c < w[0].c+w[1].c){ ///
					ans+=tmpmin.c;
					x[tmpmin.id].u=true;
					cnt[tmpmin.t]--;
				}
				else {
					ans+=w[0].c+w[1].c;
					x[w[0].id].u=true;
					x[w[1].id].u=true;
					cnt[w[1].t]--;
					cnt[w[0].t]--;
					cnt[1]++;
				}
				cnt[1]++;
			}
			else if (tmax-1>cnt[1] && w.size()==3){
				if (tmpmin.c+w[0].c < w[0].c+w[1].c+w[2].c){ ///
					ans+=tmpmin.c+w[0].c;
					x[tmpmin.id].u=true;
					x[w[0].id].u=true;
					cnt[tmpmin.t]--;
					cnt[w[0].t]--;
					cnt[1]++;
				}
				else {
					ans+=w[0].c+w[1].c+w[2].c;
					x[w[0].id].u=true;
					x[w[1].id].u=true;
					x[w[2].id].u=true;
					cnt[w[1].t]--;
					cnt[w[0].t]--;
					cnt[w[2].t]--;
					cnt[1]+=2;
				}
				cnt[1]++;
			}
			else{
				if (tmpmin.c < w[0].c){
					ans+=tmpmin.c;
					x[tmpmin.id].u=true;
					cnt[tmpmin.t]--;
				}
				else {
					ans+=w[0].c;
					x[w[0].id].u=true;
					cnt[w[0].t]--;
				}
				cnt[1]++;
			}
	}
	cout<<ans<<"\n";
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,t1,t2,cnt[3001],l,id,tt[3001];
long long ans,tans;
vector <int> c[3001];
int main(){
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].push_back(t2);
	}
	for (int i=2;i<=m;i++)
		sort(c[i].begin(),c[i].end());
	ans=(long long)1e18;
	for (int v=cnt[1];v<=n;v++){
		l=v-cnt[1];
		tans=0;
		id=0;
		for (int i=2;i<=m;i++)
			if (cnt[i]>=v){
				l-=(cnt[i]-v+1);
				for (int j=0;j<cnt[j]-v+1;j++)
					tans+=c[i][j];
				for (int j=cnt[j]-v+1;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
			else {
				for (int j=0;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
		if (l<0)
			continue;
		sort(tt,tt+id);
		for (int i=0;i<l;i++)
			tans+=tt[i];
		ans=min(tans,ans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,t1,t2,cnt[3001],l,id,tt[3001];
long long ans,tans;
vector <int> c[3001];
int main(){
	cin>>n>>m;
	fill(cnt,cnt+m+1,0);
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].push_back(t2);
	}
	for (int i=2;i<=m;i++)
		sort(c[i].begin(),c[i].end());
	ans=(long long)1e18;
	for (int v=cnt[1];v<=n;v++){
		l=v-cnt[1];
		tans=0;
		id=0;
		for (int i=2;i<=m;i++)
			if (cnt[i]>=v && cnt[i]>0){
				l-=(cnt[i]-v+1);
				for (int j=0;j<cnt[i]-v+1;j++)
					tans+=c[i][j];
				for (int j=cnt[i]-v+1;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
			else {
				for (int j=0;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
		if (l<0)
			continue;
		sort(tt,tt+id);
		//cout<<l<<" "<<v<<" "<<tans<<"\n";
		for (int i=0;i<l;i++)
			tans+=tt[i];
		ans=min(tans,ans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include <bits/stdc++.h>
#define inf 1e18
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3011],t1,t2,tmax,ans;
vector <LL> c[3011],tmp;
int main(){
	ans=inf;
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].pb(t2);
	}
	for (int j=2;j<=m;j++)
	sort(c[j].begin(),c[j].end());
	for (int j=2;j<=m;j++)
		if (cnt[j]<cnt[1]-1)
		for (int k=0;k<cnt[j];k++)
		tmp.pb(c[j][k]);

	for (int i=cnt[1];i<=n;i++){//
		int need = i-cnt[1];
		bool ok=true;
		LL tans=0;
		for (int j=2;j<=m && ok;j++)
		if (cnt[j]>=i){
			for (int k=0;k<cnt[j]-i+1;k++)
			tans+=c[j][k];
			need-=(cnt[j]-i+1);
			if (need<0){
				ok=false;
				break;
			}
			for (int k=cnt[j]-i+1;k<(int)c[j].size();k++)
			tmp.pb(c[j][k]);
		}
		else if (cnt[j]+1==i)
			for (int k=0;k<(int)c[j].size();k++)
				tmp.pb(c[j][k]);
		if (need>0){
			sort(tmp.begin(),tmp.end());
			if (tmp.size()>=need)
			for (int i=0;i<need;i++){
				tans+=tmp[i];
			}
			else ok=false;
		}
		if (ok) ans=min(ans,tans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include <bits/stdc++.h>
#define inf 1e18
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3011],t1,t2,tmax,ans,num;
vector <LL> c[3011],tmp;
int main(){
	ans=inf;
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].pb(t2);
	}
	for (int j=2;j<=m;j++)
	if ((int)c[j].size()>0)
	sort(c[j].begin(),c[j].end());
	for (int i=cnt[1];i<=m;i++){//
		tmp.clear();
		LL need = i-cnt[1];
		bool ok=true;
		LL tans=0;
		for (int j=2;j<=m && ok;j++)
		if (cnt[j]>=i){
			for (int k=0;k<cnt[j]-i+1;k++)
			tans+=c[j][k];
			need-=(cnt[j]-i+1);
			if (need<0){
				ok=false;
				break;
			}
			for (int k=cnt[j]-i+1;k<(int)c[j].size();k++)
			tmp.pb(c[j][k]);
		}
		else
		for (int k=0;k<(int)c[j].size();k++)
				tmp.pb(c[j][k]);
		if (need>0){
			if ((int)tmp.size()>0)
				sort(tmp.begin(),tmp.end());
			if ((int)tmp.size()>=need)
			for (int i=0;i<need;i++){
				tans+=tmp[i];
			}
			else ok=false;
		}
		//if (ok) cout<<i<<" "<<tans<<"\n";
		if (ok) ans=min(ans,tans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include <bits/stdc++.h>
#define inf 2e9
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3001],t1,t2,tmax;
struct ugh{
	int c,t;
	int id;
	bool u;
};
vector <ugh> x,w;
LL ans;
bool done(){
	for (int i=2;i<=m;i++)
	if (cnt[i]>=cnt[1])
	return false;
	return true;
}
bool cmp(ugh A,ugh B){
	if (A.c!=B.c)
		return A.c<B.c;
	return cnt[A.t]>cnt[B.t];
}
int main(){
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1){
			ugh tmp = {t2,t1,false};
			x.pb(tmp);
		}
	}
	ans=0;
	sort(x.begin(),x.end(),cmp);
	for (int i=0;i<(int)x.size();i++)
	x[i].id=i;
	while (!done()){
		//cout<<ans<<"\n";
		//find max vote
		LL tmax=-1;
		w.clear();
		for (int i=2;i<=n;i++)
		if (cnt[i]>tmax)
			tmax=cnt[i];
		//find max vote min cost
		LL minc=inf;
		ugh tmpmin;
		for(int i=0;i<(int)x.size();i++)
		if (!x[i].u){//each voter
			if (cnt[x[i].t]==tmax){
				if (x[i].c<minc){
					minc=x[i].c;
					tmpmin=x[i];
				}
			}
			else if (w.size()<3){
				w.pb(x[i]);
			}
		}
		//find not max vote but min cost *3
		if (cnt[1]-1==tmax){
				if (w.size()<2 || tmpmin.c < w[0].c+w[1].c){ ///
					ans+=tmpmin.c;
					x[tmpmin.id].u=true;
					cnt[tmpmin.t]--;
				}
				else {
					ans+=w[0].c+w[1].c;
					x[w[0].id].u=true;
					x[w[1].id].u=true;
					cnt[w[1].t]--;
					cnt[w[0].t]--;
					cnt[1]++;
				}
				cnt[1]++;
			}
			else if (tmax-1>cnt[1] && w.size()==3){
				if (tmpmin.c+w[0].c < w[0].c+w[1].c+w[2].c){ ///
					ans+=tmpmin.c+w[0].c;
					x[tmpmin.id].u=true;
					x[w[0].id].u=true;
					cnt[tmpmin.t]--;
					cnt[w[0].t]--;
					cnt[1]++;
				}
				else {
					ans+=w[0].c+w[1].c+w[2].c;
					x[w[0].id].u=true;
					x[w[1].id].u=true;
					x[w[2].id].u=true;
					cnt[w[1].t]--;
					cnt[w[0].t]--;
					cnt[w[2].t]--;
					cnt[1]+=2;
				}
				cnt[1]++;
			}
			else{
				if (tmpmin.c < w[0].c){
					ans+=tmpmin.c;
					x[tmpmin.id].u=true;
					cnt[tmpmin.t]--;
				}
				else {
					ans+=w[0].c;
					x[w[0].id].u=true;
					cnt[w[0].t]--;
				}
				cnt[1]++;
			}
	}
	cout<<ans<<"\n";
	return 0;
}


#include <bits/stdc++.h>
#define inf 1e18
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3011],t1,t2,tmax,ans,num;
vector <LL> c[3011],tmp;
int main(){
	ans=inf;
	cin>>n>>m;
	fill(cnt,cnt+m+1,0);
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].pb(t2);
	}
	for (int j=2;j<=m;j++)
	if ((int)c[j].size()>0)
	sort(c[j].begin(),c[j].end());
	for (int i=cnt[1];i<=m;i++){//
		if (!tmp.empty())
			tmp.clear();
		LL need = i-cnt[1];
		bool ok=true;
		LL tans=0;
		for (int j=2;j<=m && ok;j++)
		if (cnt[j]>=i){
			for (int k=0;k<cnt[j]-i+1;k++)
			tans+=c[j][k];
			need-=(cnt[j]-i+1);
			if (need<0){
				ok=false;
				break;
			}
			for (int k=cnt[j]-i+1;k<(int)c[j].size();k++)
			tmp.pb(c[j][k]);
		}
		else
		for (int k=0;k<(int)c[j].size();k++)
				tmp.pb(c[j][k]);
		if (need>0){
			if ((int)tmp.size()>0)
				sort(tmp.begin(),tmp.end());
			if ((int)tmp.size()>=need)
			for (int j=0;j<need;j++){
				tans+=tmp[j];
			}
			else ok=false;
		}
		//if (ok) cout<<i<<" "<<tans<<"\n";
		if (ok && need==0) ans=min(ans,tans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include <bits/stdc++.h>
#define inf 1e18
#define pb push_back
#define mp make_pair
#define ss second
#define ff first
#define LL long long
using namespace std;
LL n,m,cnt[3011],t1,t2,tmax,ans,num;
vector <LL> c[3011],tmp;
int main(){
	ans=inf;
	cin>>n>>m;
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].pb(t2);
	}
	for (int j=2;j<=m;j++)
	if ((int)c[j].size()>0)
	sort(c[j].begin(),c[j].end());
	for (int i=cnt[1];i<=n;i++){//
		tmp.clear();
		LL need = i-cnt[1];
		bool ok=true;
		LL tans=0;
		for (int j=2;j<=m && ok;j++)
		if (cnt[j]>=i){
			for (int k=0;k<cnt[j]-i+1;k++)
			tans+=c[j][k];
			need-=(cnt[j]-i+1);
			if (need<0){
				ok=false;
				break;
			}
			for (int k=cnt[j]-i+1;k<(int)c[j].size();k++)
			tmp.pb(c[j][k]);
		}
		else
		for (int k=0;k<(int)c[j].size();k++)
				tmp.pb(c[j][k]);
		if (need>0){
			if ((int)tmp.size()>0)
				sort(tmp.begin(),tmp.end());
			if ((int)tmp.size()>=need)
			for (int i=0;i<need;i++){
				tans+=tmp[i];
			}
			else ok=false;
		}
		//if (ok) cout<<i<<" "<<tans<<"\n";
		if (ok) ans=min(ans,tans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,t1,t2,cnt[3001],l,id,tt[3001];
long long ans,tans;
vector <int> c[3001];
int main(){
	cin>>n>>m;
	fill(cnt,cnt+m+1,0);
	for (int i=0;i<n;i++){
		cin>>t1>>t2;
		cnt[t1]++;
		if (t1!=1)
			c[t1].push_back(t2);
	}
	for (int i=2;i<=m;i++)
		sort(c[i].begin(),c[i].end());
	ans=(long long)1e18;
	for (int v=cnt[1];v<=n;v++){
		l=v-cnt[1];
		tans=0;
		id=0;
		for (int i=2;i<=m;i++)
			if (cnt[i]>=v && cnt[i]>0){
				l-=(cnt[i]-v+1);
				for (int j=0;j<cnt[i]-v+1;j++)
					tans+=c[i][j];
				for (int j=cnt[j]-v+1;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
			else {
				for (int j=0;j<cnt[i];j++,id++)
					tt[id]=c[i][j];
			}
		if (l<0)
			continue;
		sort(tt,tt+id);
		//cout<<l<<" "<<v<<" "<<tans<<"\n";
		for (int i=0;i<l;i++)
			tans+=tt[i];
		ans=min(tans,ans);
	}
	cout<<ans<<"\n";
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <complex>
#include <map>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef vector<pii> vii;

int h, w;
int v[1615][1615];
int was[1615][1615];
int was1[1615][1615];
vii cur;

void dfs(int i, int j) {
    if (!was[i][j] && v[i][j]) {
        was[i][j] = 1;
        cur.push_back(pii(i, j));
        for (int i1 = -1; i1 < 2; ++i1) for (int j1 = -1; j1 < 2; ++j1) if (i1 == 0 || j1 == 0)
            dfs(i+i1, j+j1);
    }
}

void dfs1(int i, int j) {
    if (!was1[i][j] && v[i][j]) {
        was1[i][j] = 1;
        for (int i1 = -1; i1 < 2; ++i1) for (int j1 = -1; j1 < 2; ++j1) if (i1 == 0 || j1 == 0) //???
            dfs1(i+i1, j+j1);
    }
}

int f(int i, int j) {
    cur.resize(0);
    dfs(i, j);
//    double cx = 0, cy = 0;
//    int cntc = 0;
    for (int it = 0; it < cur.size(); ++it) {
        int x = cur[it].first, y = cur[it].second;
        bool in = 1;
        for (int i = -2; i <= 2; ++i) for (int j = -2; j <= 2; ++j) if (!v[x+i][y+j])
            in = 0;
//        cerr << x << ' ' << y << ' ' << in << endl;
        if (in) {
            for (int i = -3; i <= 3; ++i) for (int j = -3; j <= 3; ++j)
                was1[x+i][y+j] = 1;
        }
    }
    int res = 0;
    for (int i = 0; i < cur.size(); ++i) if (!was1[cur[i].first][cur[i].second]) {
//        cerr << cur[i].first << ' ' << cur[i].second << endl;
        ++res;
        dfs1(cur[i].first, cur[i].second);
    }
    for (int i = 0; i < cur.size(); ++i)
        v[cur[i].first][cur[i].second] = 0;
    return res;
}

int main() {
    memset(v, 0, sizeof(v));
    memset(was, 0, sizeof(was));
    memset(was1, 0, sizeof(was1));
    cin >> h >> w;
    for (int i = 0; i < h; ++i) for (int j = 0; j < w; ++j)
        scanf("%d", &v[i+5][j+5]);
    h += 20; w += 20;
    vi res;
    for (int i = 0; i < h; ++i) for (int j = 0; j < w; ++j) if (v[i][j]) {
        res.push_back(f(i, j));
    }
    sort(res.begin(), res.end());
    cout << res.size() << endl;
    for (int i = 0; i < res.size(); ++i)
        cout << res[i] << ' ';
    cout << endl;
    return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<map>
#include<ctime>
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<bitset>
#include<functional>
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define REP(i,l,r) for((i)=(l);(i)<=(r);++(i))
#define REP2(i,l,r) for((i)=(l);(i)!=(r);++(i))
using namespace std;

typedef long long LL;
typedef double ld;

const int NUM=2000+10;

int h,w;
int g[NUM][NUM],c[NUM][NUM],can[NUM][NUM];

vector< pair<int,int> > to;

void dfs(int x,int y)
{
	to.pb(mp(x,y));
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				dfs(i,j);
}

int dist(pair<int,int> a,pair<int,int> b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int dfs2(int x,int y)
{
	int ans=1;
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				ans+=dfs2(i,j);
	return ans;
}

int calc()
{
	int sum=0;
	int i;
	REP2(i,0,(int)to.size())
		if(can[to[i].x][to[i].y])
			g[to[i].x][to[i].y]=1;
	REP2(i,0,(int)to.size())
		if(g[to[i].x][to[i].y])
			sum+=dfs2(to[i].x,to[i].y)>5;
	return sum;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
#endif
	int i,j;
	scanf("%d%d",&h,&w);
	REP(i,1,h)
		REP(j,1,w)
			scanf("%dd",&g[i][j]);
	vector<int> ans;
	REP(i,1,h)
	{
		int last=0;
		REP(j,1,w)
		{
			if(g[i][j])
				++last;
			else last=0;
			if(last<=6 && !g[i][j+1])
			{
				int u=j;
				while(g[i][u])
				{
					can[i][u]=1;
					--u;
				}
			}
		}
	}
	REP(i,1,w)
	{
		int last=0;
		REP(j,1,h)
		{
			if(g[j][i])
				++last;
			else last=0;
			if(last<=6 && !g[j+1][i])
			{
				int u=j;
				while(g[u][i])
				{
					can[u][i]=1;
					--u;
				}
			}
		}
	}
	REP(i,1,h)
		REP(j,1,w)
			if(g[i][j])
			{
				to.clear();
				dfs(i,j);
				ans.pb(calc());
			}
	cout<<ans.size()<<endl;
	sort(ans.begin(),ans.end());
	REP2(i,0,(int)ans.size())
		cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<map>
#include<ctime>
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<bitset>
#include<functional>
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define REP(i,l,r) for((i)=(l);(i)<=(r);++(i))
#define REP2(i,l,r) for((i)=(l);(i)!=(r);++(i))
using namespace std;

typedef long long LL;
typedef double ld;

const int NUM=2000+10;

int h,w;
int g[NUM][NUM],c[NUM][NUM],can[NUM][NUM];

vector< pair<int,int> > to;

void dfs(int x,int y)
{
	to.pb(mp(x,y));
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				dfs(i,j);
}

int dist(pair<int,int> a,pair<int,int> b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int dfs2(int x,int y)
{
	int ans=1;
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				ans+=dfs2(i,j);
	return ans;
}

int calc()
{
	int sum=0;
	int i;
	REP2(i,0,(int)to.size())
		if(can[to[i].x][to[i].y])
			g[to[i].x][to[i].y]=1;
	REP2(i,0,(int)to.size())
		if(g[to[i].x][to[i].y])
			sum+=dfs2(to[i].x,to[i].y)>20;
	return sum;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
#endif
	int i,j;
	scanf("%d%d",&h,&w);
	REP(i,1,h)
		REP(j,1,w)
			scanf("%dd",&g[i][j]);
	vector<int> ans;
	REP(i,1,h)
	{
		int last=0;
		REP(j,1,w)
		{
			if(g[i][j])
				++last;
			else last=0;
			if(last<=10 && !g[i][j+1])
			{
				int u=j;
				while(g[i][u])
				{
					can[i][u]=1;
					--u;
				}
			}
		}
	}
	REP(i,1,w)
	{
		int last=0;
		REP(j,1,h)
		{
			if(g[j][i])
				++last;
			else last=0;
			if(last<=10 && !g[j+1][i])
			{
				int u=j;
				while(g[u][i])
				{
					can[u][i]=1;
					--u;
				}
			}
		}
	}
	/*
	REP(i,1,h)
	{
		REP(j,1,w)
			cout<<can[i][j];
		cout<<endl;
	}
	*/
	REP(i,1,h)
		REP(j,1,w)
			if(g[i][j])
			{
				to.clear();
				dfs(i,j);
				ans.pb(calc());
			}
	cout<<ans.size()<<endl;
	sort(ans.begin(),ans.end());
	REP2(i,0,(int)ans.size())
		cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<map>
#include<ctime>
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<bitset>
#include<functional>
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define REP(i,l,r) for((i)=(l);(i)<=(r);++(i))
#define REP2(i,l,r) for((i)=(l);(i)!=(r);++(i))
using namespace std;

typedef long long LL;
typedef double ld;

const int NUM=2000+10;

int h,w;
int g[NUM][NUM],c[NUM][NUM],can[NUM][NUM];

vector< pair<int,int> > to;

void dfs(int x,int y)
{
	to.pb(mp(x,y));
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				dfs(i,j);
}

int dist(pair<int,int> a,pair<int,int> b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int dfs2(int x,int y)
{
	int ans=1;
	g[x][y]=0;
	int i,j;
	REP(i,x-1,x+1)
		REP(j,y-1,y+1)
			if(g[i][j])
				ans+=dfs2(i,j);
	return ans;
}

int calc()
{
	int sum=0;
	int i;
	REP2(i,0,(int)to.size())
		if(can[to[i].x][to[i].y])
			g[to[i].x][to[i].y]=1;
	REP2(i,0,(int)to.size())
		if(g[to[i].x][to[i].y])
			sum+=dfs2(to[i].x,to[i].y)>10;
	return sum;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
#endif
	int i,j;
	scanf("%d%d",&h,&w);
	REP(i,1,h)
		REP(j,1,w)
			scanf("%dd",&g[i][j]);
	vector<int> ans;
	REP(i,1,h)
	{
		int last=0;
		REP(j,1,w)
		{
			if(g[i][j])
				++last;
			else last=0;
			if(last<=10 && !g[i][j+1])
			{
				int u=j;
				while(g[i][u])
				{
					can[i][u]=1;
					--u;
				}
			}
		}
	}
	REP(i,1,w)
	{
		int last=0;
		REP(j,1,h)
		{
			if(g[j][i])
				++last;
			else last=0;
			if(last<=10 && !g[j+1][i])
			{
				int u=j;
				while(g[u][i])
				{
					can[u][i]=1;
					--u;
				}
			}
		}
	}
	/*
	REP(i,1,h)
	{
		REP(j,1,w)
			cout<<can[i][j];
		cout<<endl;
	}
	*/
	REP(i,1,h)
		REP(j,1,w)
			if(g[i][j])
			{
				to.clear();
				dfs(i,j);
				ans.pb(calc());
			}
	cout<<ans.size()<<endl;
	sort(ans.begin(),ans.end());
	REP2(i,0,(int)ans.size())
		cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#define REP(i,m) for(int i=0;i<m;++i)
#define REPN(i,m,in) for(int i=in;i<m;++i)
#define ALL(t) (t).begin(),(t).end()
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
using namespace std;
static const int INF =500000000;
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
typedef long long int lint;
typedef pair<int,int> pi;
int h,w;

int buf[2000][2000];
int core[2000][2000];
int sum[2000][2000];
struct uf{
	int par[4000000];
	void init(){
		memset(par,-1,sizeof(par));
	}
	int root(int a){
		if(par[a]==-1) return a;
		return par[a]=root(par[a]);
	}
	void unite(int a,int b){
		a=root(a);b=root(b);
		if(a==b) return;
		par[a]=b;
	}
};
uf u,uc;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};

int id[4000005];
int main(){
	cin>>h>>w;
	REP(i,h) REP(j,w){
		scanf("%d",&buf[i+5][j+5]);
	}
	h+=10;w+=10;
	REP(i,h) REP(j,w){
		sum[i+1][j+1]=sum[i][j+1]+sum[i+1][j]-sum[i][j]+buf[i][j];
	}
	REP(i,h) REP(j,w) if(buf[i][j]){
		int tot=sum[i+3][j+3]-sum[i+3][j-3]-sum[i-3][j+3]+sum[i-3][j-3];
		core[i][j]=(tot==36);
	}
	u.init();
	uc.init();

	vector<int> res;

	REP(i,h) REP(j,w) if(buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(buf[py][px]) u.unite(i*w+j,py*w+px);
		}
	}
	REP(i,h) REP(j,w) if(core[i][j]==1){
		int sz=10;
		REPN(dx,sz,-sz) REPN(dy,sz,-sz){
			if(i+dy<h && i+dy>=0 && j+dx>=0 && j+dx<=w) core[i+dy][j+dx]|=2;
		}
	}
	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(!core[py][px] && buf[py][px]) uc.unite(i*w+j,py*w+px);
		}
	}

	int cnt=0;
	REP(i,h) REP(j,w) if( buf[i][j] && u.root(i*w+j)==i*w+j){
		id[i*w+j]=cnt++;
	}
	dump(cnt);
	res.resize(cnt);

	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j] && uc.root(i*w+j)==i*w+j){
		int belong=id[u.root(i*w+j)];
		res[belong]++;
	}

	sort(ALL(res));
	REP(i,res.size()) printf("%d\n",res[i]);

	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#define REP(i,m) for(int i=0;i<m;++i)
#define REPN(i,m,in) for(int i=in;i<m;++i)
#define ALL(t) (t).begin(),(t).end()
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
using namespace std;
static const int INF =500000000;
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
typedef long long int lint;
typedef pair<int,int> pi;
int h,w;

int buf[2000][2000];
int core[2000][2000];
int sum[2000][2000];
struct uf{
	int par[4000000];
	void init(){
		memset(par,-1,sizeof(par));
	}
	int root(int a){
		if(par[a]==-1) return a;
		return par[a]=root(par[a]);
	}
	void unite(int a,int b){
		a=root(a);b=root(b);
		if(a==b) return;
		par[a]=b;
	}
};
uf u,uc;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};

int id[4000005];
int main(){
	cin>>h>>w;
	REP(i,h) REP(j,w){
		scanf("%d",&buf[i+5][j+5]);
	}
	h+=10;w+=10;
	REP(i,h) REP(j,w){
		sum[i+1][j+1]=sum[i][j+1]+sum[i+1][j]-sum[i][j]+buf[i][j];
	}
	REP(i,h) REP(j,w) if(buf[i][j]){
		int tot=sum[i+3][j+3]-sum[i+3][j-3]-sum[i-3][j+3]+sum[i-3][j-3];
		core[i][j]=(tot==36);
	}
	u.init();
	uc.init();

	vector<int> res;

	REP(i,h) REP(j,w) if(buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(buf[py][px]) u.unite(i*w+j,py*w+px);
		}
	}
	REP(i,h) REP(j,w) if(core[i][j]==1){
		int sz=10;
		REPN(dx,sz,-sz) REPN(dy,sz,-sz){
			if(i+dy<h && i+dy>=0 && j+dx>=0 && j+dx<=w) core[i+dy][j+dx]|=2;
		}
	}
	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(!core[py][px] && buf[py][px]) uc.unite(i*w+j,py*w+px);
		}
	}

	int cnt=0;
	REP(i,h) REP(j,w) if( buf[i][j] && u.root(i*w+j)==i*w+j){
		id[i*w+j]=cnt++;
	}
	dump(cnt);
	res.resize(cnt);

	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j] && uc.root(i*w+j)==i*w+j){
		int belong=id[u.root(i*w+j)];
		res[belong]++;
	}

	sort(ALL(res));
	printf("%d\n",res.size());
	REP(i,res.size()) printf("%d\n",res[i]);

	return 0;
}


#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#define REP(i,m) for(int i=0;i<m;++i)
#define REPN(i,m,in) for(int i=in;i<m;++i)
#define ALL(t) (t).begin(),(t).end()
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
using namespace std;
static const int INF =500000000;
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
typedef long long int lint;
typedef pair<int,int> pi;
int h,w;

int buf[2000][2000];
int core[2000][2000];
int sum[2000][2000];
struct uf{
	int par[4000000];
	void init(){
		memset(par,-1,sizeof(par));
	}
	int root(int a){
		if(par[a]==-1) return a;
		return par[a]=root(par[a]);
	}
	void unite(int a,int b){
		a=root(a);b=root(b);
		if(a==b) return;
		par[a]=b;
	}
};
uf u,uc;
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};

int id[4000005];
int main(){
	cin>>h>>w;
	REP(i,h) REP(j,w){
		scanf("%d",&buf[i+5][j+5]);
	}
	h+=10;w+=10;
	REP(i,h) REP(j,w){
		sum[i+1][j+1]=sum[i][j+1]+sum[i+1][j]-sum[i][j]+buf[i][j];
	}
	REP(i,h) REP(j,w) if(buf[i][j]){
		int tot=sum[i+3][j+3]-sum[i+3][j-3]-sum[i-3][j+3]+sum[i-3][j-3];
		core[i][j]=(tot==36);
	}
	u.init();
	uc.init();

	vector<int> res;

	REP(i,h) REP(j,w) if(buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(buf[py][px]) u.unite(i*w+j,py*w+px);
		}
	}
	REP(i,h) REP(j,w) if(core[i][j]&1){
		int sz=7;
		REPN(dx,sz,-sz) REPN(dy,sz,-sz){
			if(i+dy<h && i+dy>=0 && j+dx>=0 && j+dx<=w) core[i+dy][j+dx]|=2;
		}
	}
	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j]){
		REP(d,4){
			int px=j+dx[d],py=i+dy[d];
			if(px<0 || py<0 || px>=w || py>=h) continue;
			if(!core[py][px] && buf[py][px]) uc.unite(i*w+j,py*w+px);
		}
	}

	int cnt=0;
	REP(i,h) REP(j,w) if( buf[i][j] && u.root(i*w+j)==i*w+j){
		id[i*w+j]=cnt++;
	}
	res.resize(cnt);

	REP(i,h) REP(j,w) if(!core[i][j] && buf[i][j] && uc.root(i*w+j)==i*w+j){
		int belong=id[u.root(i*w+j)];
		res[belong]++;
	}

	sort(ALL(res));
	printf("%d\n",res.size());
	REP(i,res.size()) printf("%d\n",res[i]);

	return 0;
}


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

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <memory.h>

using namespace std;

#define REP(i,n) for(int i=0;i<n;++i)
#define ABS(n) ((n)<0 ? -(n) : (n))
#define SQR(a) (a)*(a)
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
#define MP make_pair
#define PB push_back
#define FILL(a) memset(a,0,sizeof(a));
#define COPY(a,b) memcpy(a,b,sizeof (b));
#define SI(a) (int)((a).size())
#define ALL(a) (a).begin(),(a).end()
#define y1 yyyyy1
#define prev prevvvvv
#define LL long long
const double PI = 2*acos(0.0);
const double EPS = 1e-8;
const int INF = (1<<30)-1;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

int m, n;
int a[1700][1700];
vector<pair<int,int> > coords;

void dfs1 (int r, int c) {
    if (a[r][c] != 1) return;
    coords.push_back(make_pair(r,c));
    a[r][c] = 2;
    REP(i,4) dfs1(r+dr[i], c+dc[i]);
}

int fillWith(int r, int c, int col1, int col2) {
    if (a[r][c] != col1) return 0;
    a[r][c] = col2;
    int res = 1;
    REP(i,4) res += fillWith(r+dr[i], c+dc[i], col1, col2);
    return res;
}

void buildCoords(int r, int c) {
    coords.clear();
    dfs1 (r, c);
}

const int D = 5;

inline double getNeighborsShare(int r, int c){
    int res = 0;
    for (int cr = max<int>(r-D,0); cr <= min<int>(r+D,m-1); ++cr){
        for (int cc = max<int>(c-D,0); cc <= min<int>(c+D,n-1); ++cc) {
            if (a[cr][cc] != 0) ++res;
        }
    }
    //cout << (res + 0.) / (2*D+1) / (2*D+1) << endl;
    return (res + 0.) / (2*D+1) / (2*D+1);
}

int getRays (int r, int c){
    buildCoords(r, c);
    REP(i,SI(coords)){
        int r = coords[i].first;
        int c = coords[i].second;
        if (getNeighborsShare (r, c) > 0.5) a[r][c] = 3;
    }

    /*
    REP(i,m) {
        REP(j,n) if (a[i][j] == 0) cout << " ";
        else cout << a[i][j];
        cout << endl;
    }
    */

    int ans = 0;
    REP(i,SI(coords)) if (a[coords[i].first][coords[i].second] == 2) {
        if (fillWith(coords[i].first, coords[i].second, 2, 3) > 5) ++ans;;
    }
    REP(i,SI(coords)) a[coords[i].first][coords[i].second] = 0;
    return ans;
}

int main(){
	//freopen ("input.txt", "r", stdin);
	//freopen ("output.txt", "w", stdout);
    scanf ("%d%d", &m, &n);
    REP(i,m) {
        REP(j,n) scanf ("%d", &a[i+1][j+1]);
    }
    m += 2; n += 2;

    vector<int> ans;

    REP(i,m) REP(j,n) if (a[i][j] != 0) ans.push_back(getRays(i, j));

    sort (ans.begin(), ans.end());
    cout << ans.size() << endl;
    REP(i,ans.size()) cout << ans[i] << " ";
	return 0;
};


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

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <memory.h>

using namespace std;

#define REP(i,n) for(int i=0;i<n;++i)
#define ABS(n) ((n)<0 ? -(n) : (n))
#define SQR(a) (a)*(a)
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
#define MP make_pair
#define PB push_back
#define FILL(a) memset(a,0,sizeof(a));
#define COPY(a,b) memcpy(a,b,sizeof (b));
#define SI(a) (int)((a).size())
#define ALL(a) (a).begin(),(a).end()
#define y1 yyyyy1
#define prev prevvvvv
#define LL long long
const double PI = 2*acos(0.0);
const double EPS = 1e-8;
const int INF = (1<<30)-1;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

int m, n;
int a[1700][1700];
vector<pair<int,int> > coords;

void dfs1 (int r, int c) {
    if (a[r][c] != 1) return;
    coords.push_back(make_pair(r,c));
    a[r][c] = 2;
    REP(i,4) dfs1(r+dr[i], c+dc[i]);
}

int fillWith(int r, int c, int col1, int col2) {
    if (a[r][c] != col1) return 0;
    a[r][c] = col2;
    int res = 1;
    REP(i,4) res += fillWith(r+dr[i], c+dc[i], col1, col2);
    return res;
}

void buildCoords(int r, int c) {
    coords.clear();
    dfs1 (r, c);
}

const int D = 5;

inline double getNeighborsShare(int r, int c){
    int res = 0;
    for (int cr = max<int>(r-D,0); cr <= min<int>(r+D,m-1); ++cr){
        for (int cc = max<int>(c-D,0); cc <= min<int>(c+D,n-1); ++cc) {
            if (a[cr][cc] != 0) ++res;
        }
    }
    //cout << (res + 0.) / (2*D+1) / (2*D+1) << endl;
    return (res + 0.) / (2*D+1) / (2*D+1);
}

int getRays (int r, int c){
    buildCoords(r, c);
    REP(i,SI(coords)){
        int r = coords[i].first;
        int c = coords[i].second;
        if (getNeighborsShare (r, c) > 0.45) a[r][c] = 3;
    }

    /*
    REP(i,m) {
        REP(j,n) if (a[i][j] == 0) cout << " ";
        else cout << a[i][j];
        cout << endl;
    }
    */

    int ans = 0;
    REP(i,SI(coords)) if (a[coords[i].first][coords[i].second] == 2) {
        if (fillWith(coords[i].first, coords[i].second, 2, 3) > 5) ++ans;;
    }
    REP(i,SI(coords)) a[coords[i].first][coords[i].second] = 0;
    return ans;
}

int main(){
	//freopen ("input.txt", "r", stdin);
	//freopen ("output.txt", "w", stdout);
    scanf ("%d%d", &m, &n);
    REP(i,m) {
        REP(j,n) scanf ("%d", &a[i+1][j+1]);
    }
    m += 2; n += 2;

    vector<int> ans;

    REP(i,m) REP(j,n) if (a[i][j] != 0) ans.push_back(getRays(i, j));

    sort (ans.begin(), ans.end());
    cout << ans.size() << endl;
    REP(i,ans.size()) cout << ans[i] << " ";
	return 0;
};


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

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <memory.h>

using namespace std;

#define REP(i,n) for(int i=0;i<n;++i)
#define ABS(n) ((n)<0 ? -(n) : (n))
#define SQR(a) (a)*(a)
#define MIN(a,b) (a<b?a:b)
#define MAX(a,b) (a>b?a:b)
#define MP make_pair
#define PB push_back
#define FILL(a) memset(a,0,sizeof(a));
#define COPY(a,b) memcpy(a,b,sizeof (b));
#define SI(a) (int)((a).size())
#define ALL(a) (a).begin(),(a).end()
#define y1 yyyyy1
#define prev prevvvvv
#define LL long long
const double PI = 2*acos(0.0);
const double EPS = 1e-8;
const int INF = (1<<30)-1;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

int m, n;
int a[1700][1700];
vector<pair<int,int> > coords;

void dfs1 (int r, int c) {
    if (a[r][c] != 1) return;
    coords.push_back(make_pair(r,c));
    a[r][c] = 2;
    REP(i,4) dfs1(r+dr[i], c+dc[i]);
}

int fillWith(int r, int c, int col1, int col2) {
    if (a[r][c] != col1) return 0;
    a[r][c] = col2;
    int res = 1;
    REP(i,4) res += fillWith(r+dr[i], c+dc[i], col1, col2);
    return res;
}

void buildCoords(int r, int c) {
    coords.clear();
    dfs1 (r, c);
}

const int D = 5;

inline double getNeighborsShare(int r, int c){
    int res = 0;
    for (int cr = max<int>(r-D,0); cr <= min<int>(r+D,m-1); ++cr){
        for (int cc = max<int>(c-D,0); cc <= min<int>(c+D,n-1); ++cc) {
            if (a[cr][cc] != 0) ++res;
        }
    }
    //cout << (res + 0.) / (2*D+1) / (2*D+1) << endl;
    return (res + 0.) / (2*D+1) / (2*D+1);
}

int getRays (int r, int c){
    buildCoords(r, c);
    REP(i,SI(coords)){
        int r = coords[i].first;
        int c = coords[i].second;
        if (getNeighborsShare (r, c) > 0.4) a[r][c] = 3;
    }

    /*
    REP(i,m) {
        REP(j,n) if (a[i][j] == 0) cout << " ";
        else cout << a[i][j];
        cout << endl;
    }
    */

    int ans = 0;
    REP(i,SI(coords)) if (a[coords[i].first][coords[i].second] == 2) {
        if (fillWith(coords[i].first, coords[i].second, 2, 3) > 5) ++ans;;
    }
    REP(i,SI(coords)) a[coords[i].first][coords[i].second] = 0;
    return ans;
}

int main(){
	//freopen ("input.txt", "r", stdin);
	//freopen ("output.txt", "w", stdout);
    scanf ("%d%d", &m, &n);
    REP(i,m) {
        REP(j,n) scanf ("%d", &a[i+1][j+1]);
    }
    m += 2; n += 2;

    vector<int> ans;

    REP(i,m) REP(j,n) if (a[i][j] != 0) ans.push_back(getRays(i, j));

    sort (ans.begin(), ans.end());
    cout << ans.size() << endl;
    REP(i,ans.size()) cout << ans[i] << " ";
	return 0;
};


/* hanhanw v1.3 */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
// for Online Judge or Contests
#define MSET(x,y) memset(x,y,sizeof(x))
#define FOR(x,y) for(__typeof(y.begin())x=y.begin();x!=y.end();x++)
#define SZ(x) ((int)x.size())
#define PB push_back
#define MP(x,y) make_pair(x,y)

using namespace std;
//
typedef long long LL;
typedef unsigned long long uLL;
typedef long double LD;
typedef pair<int,int> PII;
// start here OAO~

const int N = 1624;

int n,m;
int vst[N][N],calc[N][N];
int in[N][N];
int na,ans[N*N];
int fr,bk;
PII que[N*N];

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

inline void BFS(int stx, int sty){
	fr=bk=0;
	que[bk++] = MP(stx,sty);
	vst[stx][sty] = ++na;
	while (fr < bk){
		int x=que[fr].first;
		int y=que[fr].second;
		fr++;
		for (int i=0; i<4; i++){
			int nx=x+px[i];
			int ny=y+py[i];
			if (!vst[nx][ny] && in[nx][ny]){
				vst[nx][ny] = na;
				que[bk++] = MP(nx,ny);
			}
		}
	}
}
int main(int argc, char** argv){
//	freopen("01.in.txt","r", stdin);

	scanf("%d %d", &n, &m); getchar();
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			in[i][j] = getchar() - '0';
			getchar();
		}
	}
	na=0;
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			if (!vst[i][j] && in[i][j]){
				BFS(i,j);
			}
		}
	}
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			if (in[i][j] && in[i+1][j] && in[i+2][j] && !calc[i][j] && !calc[i+1][j] && !calc[i+2][j]){
				int cnt=0;
				for (int k=-1; k<2; k+=2){
					cnt=in[i-1][j] + in[i+3][j];
					cnt+=in[i][j+k]+in[i+1][j+k]+in[i+2][j+k];
					if (cnt) continue;
					cnt+=in[i-1][j-k]+in[i+3][j-k];
					if (!cnt)
						ans[vst[i][j]]++;
					else {
						if (cnt == 2) continue;
						ans[vst[i][j]]++;
					}
					calc[i][j]++;
					calc[i+1][j]++;
					calc[i+2][j]++;
				//	if (vst[i][j] == 2) printf("%d %d\n", i, j);
				}
			}
		}
	}
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			if (in[i][j] && in[i][j+1] && in[i][j+2] && !calc[i][j] && !calc[i][j+1] && !calc[i][j+2]){
				int cnt=0;
				for (int k=-1; k<2; k+=2){
					cnt=in[i][j-1] + in[i][j+3];
					cnt+=in[i+k][j]+in[i+k][j+1]+in[i+k][j+2];
					if (cnt) continue;
					cnt+=in[i-k][j-1]+in[i-k][j+3];
					if (!cnt)
						ans[vst[i][j]]++;
					else {
						if (cnt == 2) continue;
						ans[vst[i][j]]++;
					}
					calc[i][j]++;
					calc[i][j+1]++;
					calc[i][j+2]++;
				//	if (vst[i][j] == 2) printf("%d %d\n", i, j);
				}
			}
		}
	}

	printf("%d\n", na);
	sort(ans+1,ans+1+na);
	for (int i=1; i<=na; i++)
		printf("%d%c", ans[i], i==na ? '\n' : ' ');

	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;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[11];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 10){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[10]))if(ok)rep(j, i){
					li x0 = neighbor[10][i].F, y0 = neighbor[10][i].S;
					li x1 = neighbor[10][j].F, y1 = neighbor[10][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(15 * 15 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 11)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[11];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 10){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[10]))if(ok)rep(j, i)if(ok){
					li x0 = neighbor[10][i].F, y0 = neighbor[10][i].S;
					li x1 = neighbor[10][j].F, y1 = neighbor[10][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(17 * 17 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 11)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}else{
					rep(d, 4)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		stamp++;
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			type[x][y] = stamp;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[13];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 12){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(inserted.count(MP(nx, ny))) continue;
							if(!mp[nx][ny]) continue;
							inserted.insert(MP(nx, ny));
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[12]))if(ok)rep(j, i){
					li x0 = neighbor[12][i].F, y0 = neighbor[12][i].S;
					li x1 = neighbor[12][j].F, y1 = neighbor[12][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(20 * 20 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 13)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[11];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 10){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[10]))if(ok)rep(j, i)if(ok){
					li x0 = neighbor[10][i].F, y0 = neighbor[10][i].S;
					li x1 = neighbor[10][j].F, y1 = neighbor[10][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(15 * 15 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 11)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}else{
					rep(d, 2)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[13];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 12){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[12]))if(ok)rep(j, i){
					li x0 = neighbor[12][i].F, y0 = neighbor[12][i].S;
					li x1 = neighbor[12][j].F, y1 = neighbor[12][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(20 * 20 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 13)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[11];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 10){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[10]))if(ok)rep(j, i){
					li x0 = neighbor[10][i].F, y0 = neighbor[10][i].S;
					li x1 = neighbor[10][j].F, y1 = neighbor[10][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(15 * 15 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 11)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}else{
					rep(d, 4)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <bitset>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <algorithm>
//#include <sys/time.h>
using namespace std;
#define li        int
#define rep(i,to) for(li i=0;i<((li)(to));++i)
#define pb        push_back
#define sz(v)     ((li)(v).size())
#define bit(n)    (1ll<<(li)(n))
#define all(vec)  (vec).begin(),(vec).end()
#define each(i,c) for(__typeof((c).begin()) i=(c).begin();i!=(c).end();i++)
#define MP        make_pair
#define F         first
#define S         second

#define MAX 1650
li n, m;
li mp[MAX][MAX];
li used[MAX][MAX];
li checked[MAX][MAX];
li type[MAX][MAX];
li stamp = 0;
li dx[] = {1, 0, -1, 0, 1, 1, -1, -1};
li dy[] = {0, 1, 0, -1, 1, -1, 1, -1};
vector<li> ans;

int main()
{
	memset(used, false, sizeof(used));
	memset(checked, false, sizeof(checked));
	cin >> n >> m;

	rep(i, n)rep(j, m) cin >> mp[i][j];
	rep(i, n)rep(j, m)if(mp[i][j] && !used[i][j]){
		vector<pair<li, li> > q;
		q.pb(MP(i, j));
		used[i][j] = true;
		li cnt = 0;

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			rep(dir, 8){
				li nx = x + dx[dir];
				li ny = y + dy[dir];
				if(nx < 0 || n <= nx) continue;
				if(ny < 0 || m <= ny) continue;
				if(!mp[nx][ny]) continue;
				if(used[nx][ny]) continue;
				used[nx][ny] = true;
				q.pb(MP(nx, ny));
			}
		}

		rep(index, sz(q)){
			li x = q[index].F;
			li y = q[index].S;
			stamp++;

			if(!checked[x][y]){
				checked[x][y] = true;
				vector<pair<li, li> > neighbor[11];
				neighbor[0].pb(MP(x, y));
				set<pair<li, li> > inserted;
				inserted.insert(MP(x, y));

				rep(d, 10){
					rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						rep(dir, 8){
							li nx = cx + dx[dir];
							li ny = cy + dy[dir];
							if(nx < 0 || n <= nx) continue;
							if(ny < 0 || m <= ny) continue;
							if(!mp[nx][ny]) continue;
							if(type[nx][ny] == stamp) continue;
							type[nx][ny] = stamp;
							neighbor[d + 1].pb(MP(nx, ny));
						}
					}
				}

				bool ok = true;
				rep(i, sz(neighbor[10]))if(ok)rep(j, i)if(ok){
					li x0 = neighbor[10][i].F, y0 = neighbor[10][i].S;
					li x1 = neighbor[10][j].F, y1 = neighbor[10][j].S;
					li dist = (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
					if(13 * 13 < dist) ok = false;
				}

				if(ok){
					cnt++;
					rep(d, 11)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}else{
					rep(d, 4)rep(i, sz(neighbor[d])){
						li cx = neighbor[d][i].F;
						li cy = neighbor[d][i].S;
						checked[cx][cy] = true;
					}
				}
			}
		}

		ans.pb(cnt);
	}

	sort(all(ans));

	cout << sz(ans) << endl;
	rep(i, sz(ans)) cout << ans[i] << " "; cout << endl;
}


/*
ID: espr1t
TASK:
KEYWORDS:
*/

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;
FILE *in; FILE *out;

const int MAX = 1604;

int n, m;
int a[MAX][MAX];
int dist[MAX][MAX];
int dir[8][2] = { {-1, 0}, {0, 1}, {1, 0}, {0, -1},
                  {-1, -1}, {-1, 1}, {1, -1}, {1, 1} };

const int SUN = 2;
const int RAY = 3;
const int VIS = 4;

int count(int row, int col) {
    int cnt = 0;
    for (int i = 0; i < 8; i++) {
        int nrow = row + dir[i][0]; if (nrow < 0 || nrow >= n) continue;
        int ncol = col + dir[i][1]; if (ncol < 0 || ncol >= m) continue;
        if (a[nrow][ncol] != 0)
            cnt++;
    }
    return cnt;
}

int clearRay(int row, int col) {
    int ret = 1;
    queue < pair <int, int> > q;
    q.push(make_pair(row, col)); a[row][col] = VIS;
    while (!q.empty()) {
        row = q.front().first; col = q.front().second; q.pop();
        for (int i = 0; i < 8; i++) {
            int nrow = row + dir[i][0]; if (nrow < 0 || nrow >= n) continue;
            int ncol = col + dir[i][1]; if (ncol < 0 || ncol >= m) continue;
            if (a[nrow][ncol] == RAY && dist[nrow][ncol] >= 4) {
                a[nrow][ncol] = VIS; ret++;
                q.push(make_pair(nrow, ncol));
            }
        }
    }
    return ret;
}

int eval(int row, int col) {
    int ans = 0;
    queue < pair <int, int> > q;
    vector < pair <int, int> > v;

    q.push(make_pair(row, col));
    a[row][col] = (count(row, col) >= 8 ? SUN : RAY);
    while (!q.empty()) {
        row = q.front().first; col = q.front().second; q.pop();
        v.push_back(make_pair(row, col));
        for (int i = 0; i < 8; i++) {
            int nrow = row + dir[i][0]; if (nrow < 0 || nrow >= n) continue;
            int ncol = col + dir[i][1]; if (ncol < 0 || ncol >= m) continue;
            if (a[nrow][ncol] == 1) {
                a[nrow][ncol] = (count(nrow, ncol) >= 8 ? SUN : RAY);
//                fprintf(stderr, "  >> (%d, %d) became %d\n", nrow, ncol, a[nrow][ncol]);
                q.push(make_pair(nrow, ncol));
            }
        }
    }

    for (int i = 0; i < (int)v.size(); i++) {
        int row = v[i].first, col = v[i].second;
        if (a[row][col] == SUN) {
            a[row][col] = VIS;
            q.push(make_pair(row, col));
            dist[row][col] = 0;
        }
    }

    vector < pair <int, pair <int, int> > > rays;
    while (!q.empty()) {
        row = q.front().first; col = q.front().second; q.pop();
        for (int i = 0; i < 8; i++) {
            int nrow = row + dir[i][0]; if (nrow < 0 || nrow >= n) continue;
            int ncol = col + dir[i][1]; if (ncol < 0 || ncol >= m) continue;
            if (a[nrow][ncol] == RAY && dist[nrow][ncol] == -1) {
                dist[nrow][ncol] = dist[row][col] + 1;
//                fprintf(stderr, "  -- ray at distance %d\n", dist[nrow][ncol]);
                q.push(make_pair(nrow, ncol));
                if (dist[nrow][ncol] >= 4)
                    rays.push_back(make_pair(dist[nrow][ncol], make_pair(nrow, ncol)));
            }
        }
    }
//    fprintf(stderr, "%d\n", (int)rays.size());
    sort(rays.rbegin(), rays.rend());
    for (int i = 0; i < (int)rays.size(); i++) {
        row = rays[i].second.first, col = rays[i].second.second;
        if (a[row][col] != RAY)
            continue;
//        fprintf(stderr, "  -- at ray with distance %d\n", dist[row][col]);

        bool flag = true;
        for (int i = 0; i < 8; i++) {
            int nrow = row + dir[i][0]; if (nrow < 0 || nrow >= n) continue;
            int ncol = col + dir[i][1]; if (ncol < 0 || ncol >= m) continue;
            if (a[nrow][ncol] == VIS) {flag = false; break;}
        }
        if (flag) {
            ans++;
            clearRay(row, col);
        }
    }

    /*
    sort(v.begin(), v.end());
    for (int i = 0; i < (int)v.size(); i++) {
        row = v[i].first, col = v[i].second;
        if (a[row][col] == 2 && partOfRay(row, col)) {
            int cleared = clearRay(row, col);
            fprintf(stderr, "%d\n", cleared);
            if (cleared > 4)
                ans++;
        }
    }
    */
    for (int i = 0; i < (int)v.size(); i++)
        a[v[i].first][v[i].second] = 0;
    return ans;
}

int main(void) {
	in = stdin; out = stdout;
//	in = fopen("F.in", "rt"); out = fopen("F.out", "wt");

	memset(dist, -1, sizeof(dist));
	fscanf(in, "%d %d", &n, &m);
	for (int i = 0; i < n; i++)
	    for (int c = 0; c < m; c++)
	        fscanf(in, "%d", &a[i][c]);

	for (int row = 0; row < n; row++) {
	    for (int col = 0; col < m; col++) {
	        if (count(row, col) < 8)
	            a[row][col] = 2;
	    }
	}

	for (int row = 0; row < n; row++)
	    for (int col = 0; col < m; col++)
	        if (a[row][col] == 2) a[row][col] = 0;

	vector <int> ans;
	for (int row = 0; row < n; row++) {
	    for (int col = 0; col < m; col++) {
	        if (a[row][col])
	            ans.push_back(eval(row, col));
	    }
	}
	sort(ans.begin(), ans.end());
	fprintf(out, "%d\n", (int)ans.size());
	for (int i = 0; i < (int)ans.size(); i++)
	    fprintf(out, "%d%c", ans[i], i + 1 == (int)ans.size() ? '\n' : ' ');

	return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 1605
int a[N][N],visit[N][N],sum[N*N],c[N][N],qx[N*N],qy[N*N],f[N*N],cnt,n,m;
int dx[]={-1,-1,-1,0,0,1,1,1},dy[]={-1,0,1,-1,1,-1,0,1};
int find(int x){
	if (f[x]==x)return x;
	else return f[x]=find(f[x]);
}
inline void link(int x,int y){f[find(x)]=find(y);}
int S(int i1,int i2,int j1,int j2){
	i1=max(i1,1);j1=max(j1,1);i2=min(i2,n);j2=min(j2,m);
	for (int i=i1;i<=i2;++i)
		for (int j=j1;j<=j2;++j)f[(i-1)*m+j]=(i-1)*m+j;
	for (int i=i1;i<=i2;++i)
		for (int j=j1;j<=j2;++j)if (a[i][j]==0){
			for (int k=0;k<8;++k){
				int x1=i+dx[k],y1=j+dy[k];
				if (x1<i1||x1>i2||y1<j1||y1>j2||a[x1][y1]==1)continue;
				link((i-1)*m+j,(x1-1)*m+y1);
			}
		}
	int res=0;
	for (int i=i1;i<=i2;++i)
		for (int j=j1;j<=j2;++j)if (a[i][j]==0&&f[(i-1)*m+j]==(i-1)*m+j)++res;
	return res;
}
int main()
{
	//freopen("21.in.txt","r",stdin);
	//freopen("F.out","w",stdout);
	int t1=clock();
	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;++i)
		for (int j=1;j<=m;++j)if (a[i][j]==1&&S(i-5,i+5,j-5,j+5)>=2){
			//printf("%d %d\n",i,j);
			c[i][j]=1;
		}
	for (int i=1;i<=n;++i)
		for (int j=1;j<=m;++j)if (c[i][j]&&!visit[i][j]){
			int h=1,t=1;qx[h]=i;qy[h]=j;visit[i][j]=1;
			while (h<=t){
				int x=qx[h],y=qy[h];++h;
				for (int i=0;i<8;++i){
					int x1=x+dx[i],y1=y+dy[i];
					//printf("bfs %d %d\n",x1,y1);
					if (x1<1||x1>n||y1<0||y1>m||visit[x1][y1]||c[x1][y1]==0)continue;
					++t;visit[x1][y1]=1;qx[t]=x1;qy[t]=y1;c[x1][y1]=0;
				}
			}
			if (t<=15)c[i][j]=0;
			//printf("%d %d %d\n",i,j,t);
		}
	memset(visit,0,sizeof(visit));
	for (int i=1;i<=n;++i)
		for (int j=1;j<=m;++j)if (!visit[i][j]&&a[i][j]){
			//printf("%d %d\n",i,j);
			int h=1,t=1;qx[h]=i;qy[h]=j;visit[i][j]=1;++cnt;
			while (h<=t){
				int x=qx[h],y=qy[h];if (c[x][y])++sum[cnt];++h;
				for (int i=0;i<8;++i){
					int x1=x+dx[i],y1=y+dy[i];
					//printf("bfs %d %d\n",x1,y1);
					if (x1<1||x1>n||y1<0||y1>m||visit[x1][y1]||a[x1][y1]==0)continue;
					++t;visit[x1][y1]=1;qx[t]=x1;qy[t]=y1;
				}
			}
		}
	printf("%d\n",cnt);
	sort(sum+1,sum+cnt+1);
	for (int i=1;i<=cnt;++i)printf("%d%c",sum[i],i==cnt?'\n':' ');
	//printf("time=%d\n",clock()-t1);
	//system("pause");for (;;);
	return 0;
}


// by shik
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define SZ(x) ((int)(x).size())
#define FOR(it,c) for ( __typeof((c).begin()) it=(c).begin(); it!=(c).end(); it++ )
using namespace std;
#define N 1800
int n,m,img[N][N];
void input() {
    scanf("%d%d",&n,&m);
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) scanf("%d",img[i]+j);
}
int nc,cc[N][N];
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
void BFS( int x, int y, int c ) {
    queue<int> q;
    cc[x][y]=c;
    q.push(x);
    q.push(y);
    while ( !q.empty() ) {
        x=q.front(); q.pop();
        y=q.front(); q.pop();
        for ( int i=0; i<4; i++ ) {
            int nx=x+dx[i];
            int ny=y+dy[i];
            if ( img[nx][ny] && !cc[nx][ny] ) {
                cc[nx][ny]=c;
                q.push(nx);
                q.push(ny);
            }
        }
    }
}
int sum[N][N],bye[N][N];
void build() {
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) if ( img[i][j] && !cc[i][j] ) BFS(i,j,++nc);
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+img[i][j];
    for ( int i=1; i<=n-5; i++ ) for ( int j=1; j<=m-5; j++ ) {
        int now=sum[i+5][j+5]-sum[i+5][j-1]-sum[i-1][j+5]+sum[i-1][j-1];
        if ( now==36 ) {
            bye[i][j]++;
            bye[i+6][j]--;
            bye[i][j+6]--;
            bye[i+6][j+6]++;
        }
    }
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) bye[i][j]+=bye[i-1][j]+bye[i][j-1]-bye[i-1][j-1];
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) if ( bye[i][j] ) cc[i][j]=0;
    //for ( int i=1; i<=n; i++,puts("") ) for ( int j=1; j<=m; j++ ) printf("%d",cc[i][j]);
}
int BFS2( int x, int y ) {
    queue<int> q;
    cc[x][y]=0;
    q.push(x);
    q.push(y);
    int cnt=0;
    while ( !q.empty() ) {
        cnt++;
        x=q.front(); q.pop();
        y=q.front(); q.pop();
        for ( int i=0; i<4; i++ ) {
            int nx=x+dx[i];
            int ny=y+dy[i];
            if ( cc[nx][ny] ) {
                cc[nx][ny]=0;
                q.push(nx);
                q.push(ny);
            }
        }
    }
    return cnt;
}
int cnt[N*N];
void solve() {
    for ( int i=1; i<=n; i++ ) for ( int j=1; j<=m; j++ ) if ( cc[i][j] ) {
        int c=cc[i][j];
        int now=BFS2(i,j);
        if ( now>10 ) cnt[c]++;
    }
    sort(cnt+1,cnt+nc+1);
    printf("%d\n",nc);
    for ( int i=1; i<=nc; i++ ) printf("%d%c",cnt[i],i==nc?'\n':' ');
}
int main()
{
    input();
    build();
    solve();
    return 0;
}


#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <windows.h>
using namespace std;
typedef int Int;

struct cell
{
    Int x,y;
};
struct t
{
    Int x,y,dist;
};

bool picture[1602][1602];
bool newpicture[1602][1602];
bool marked[1602][1602];
bool TFO[1602][1602];
bool newTFO[1602][1602];
vector<Int> suns;

bool toprint[1602][1602];

cell comp[3000001];
Int cL=0;

Int tL;
t tail[3000001];
Int h,w;

void DFS(Int x,Int y)
{
    if (x<1 || x>h || y<1 || y>w)
    return;
    if (TFO[x][y])
    return;
    if (picture[x][y]==0)
    return;

    cL++;
    comp[cL].x=x;
    comp[cL].y=y;

    TFO[x][y]=true;

    DFS(x-1,y-1);
    DFS(x-1,y);
    DFS(x-1,y+1);
    DFS(x,y-1);
    DFS(x,y+1);
    DFS(x+1,y-1);
    DFS(x+1,y);
    DFS(x+1,y+1);

    return;
}

void DFS2(Int x,Int y)
{
    if (x<1 || x>h || y<1 || y>w)
    return;
    if (newTFO[x][y])
    return;
    if (newpicture[x][y]==0)
    return;

    newTFO[x][y]=true;

    tL++;
    tail[tL].x=x;
    tail[tL].y=y;
    tail[tL].dist=0;

    DFS2(x-1,y-1);
    DFS2(x-1,y);
    DFS2(x-1,y+1);
    DFS2(x,y-1);
    DFS2(x,y+1);
    DFS2(x+1,y-1);
    DFS2(x+1,y);
    DFS2(x+1,y+1);

    return;
}

void BFS3()
{
    Int uk=1;
    Int cx,cy;
    Int nx,ny;

    while(uk<=tL)
    {
        cx=tail[uk].x;
        cy=tail[uk].y;

        if (tail[uk].dist==6)
        {
            uk++;
            continue;
        }
        else
        {
            for (nx=cx-1;nx<=cx+1;nx++)
            {
                for (ny=cy-1;ny<=cy+1;ny++)
                {
                    if (nx<1 || nx>h || ny<1 || ny>w)
                    continue;

                    if (!newTFO[nx][ny])
                    {
                        tL++;
                        tail[tL].x=nx;
                        tail[tL].y=ny;
                        tail[tL].dist=tail[uk].dist+1;
                        newTFO[nx][ny]=true;
                    }
                }
            }
        }

        uk++;
    }

    return;
}

void DFS4(Int x,Int y)
{
    if (x<1 || x>h || y<1 || y>w)
    return;
    if (newTFO[x][y])
    return;
    if (picture[x][y]==0)
    return;

    newTFO[x][y]=true;

    DFS4(x-1,y-1);
    DFS4(x-1,y);
    DFS4(x-1,y+1);
    DFS4(x,y-1);
    DFS4(x,y+1);
    DFS4(x+1,y-1);
    DFS4(x+1,y);
    DFS4(x+1,y+1);

    return;
}

bool OK(Int x,Int y)
{
    if (x<1 || y<1 || x>h || y>w)
    return false;
    if (newpicture[x][y]==0)
    return false;

    return true;
}

int main()
{
    Int i,j,in,ja;
    Int k;
    Int ctr=0;
    Int sz;

    for (i=0;i<=1601;i++)
    {
        for (j=0;j<=1601;j++)
        {
            TFO[i][j]=false;
            newTFO[i][j]=false;
            toprint[i][j]=false;
        }
    }

    scanf("%d %d",&h,&w);

    for (i=1;i<=h;i++)
    {
        for (j=1;j<=w;j++)
        {
            scanf("%d",&k);

            if (k==0)
            {
                picture[i][j]=false;
            }
            else
            {
                picture[i][j]=true;
            }
            newpicture[i][j]=picture[i][j];
        }
    }

    for (i=1;i<=3;i++)
    {
        for (j=1;j<=h;j++)
        {
            for (in=1;in<=w;in++)
            {
                if (newpicture[j][in]==0)
                {
                    marked[j][in]=false;
                    continue;
                }

                if (!OK(j-1,in) || !OK(j-1,in+1) || !OK(j-1,in-1) || !OK(j+1,in+1) || !OK(j+1,in) || !OK(j+1,in-1) || !OK(j,in-1) || !OK(j,in+1))
                {
                    marked[j][in]=true;
                }
                else
                {
                    marked[j][in]=false;
                }
            }
        }

        for (j=1;j<=h;j++)
        {
            for (in=1;in<=w;in++)
            {
                if (marked[j][in])
                {
                    ctr++;
                    newpicture[j][in]=0;
                }
            }
        }
    }

    for (i=1;i<=h;i++)
    {
        for (j=1;j<=w;j++) ///looking for a potential sun;
        {
            if (picture[i][j]==1 && !TFO[i][j]) ///initial picture sun
            {
                cL=0;
                DFS(i,j);

                for (in=1;in<=cL;in++)
                {
                    if (newpicture[ comp[in].x ][ comp[in].y ]) ///still a part of the sun in the new
                    {
                        tL=0;
                        DFS2(comp[in].x,comp[in].y);
                        break;
                    }
                }

                BFS3();

                /**if (suns.empty())
                {
                    for (in=1;in<=h;in++)
                    {
                        for (ja=1;ja<=w;ja++)
                        {
                            if (newTFO[in][ja])
                            cout<<0;
                            else
                            cout<<picture[in][ja];
                        }
                        cout<<endl;
                    }
                }**/

                ctr=0;
                for (in=1;in<=cL;in++)
                {
                    if (!newTFO[comp[in].x][comp[in].y])
                    {
                        ctr++;
                        DFS4(comp[in].x,comp[in].y);
                    }
                }

                suns.push_back(ctr);
            }
        }
    }

    sz=suns.size();

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

    printf("%d\n",sz);

    for (i=0;i<sz;i++)
    {
        printf("%d",suns[i]);
        if (i!=sz)
        printf(" ");
    }
    printf("\n");

    return 0;
}


#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

char a[1700][1700];
int used[1700][1700], comp = 0;
int L[1700][1700], R[1700][1700], U[1700][1700], D[1700][1700];
int N, M;
char P[1700][1700];

vector < int > v;
queue <pair < int, int > > q;
int MNX[1 << 20], MNY[1 << 20], MXX[1 << 20], MXY[1 << 20];
int dx[] = {0, 1, 0, -1 };
int dy[] = {-1, 0, 1, 0 };

void scan(){
    scanf ( "%d%d", &N, &M );

    for ( int i = 1; i <= N; ++i )
        for ( int j = 1; j <= M; ++ j)
            scanf ( "%d", a[i] + j );
}

int brr = 0;
void bfs ( char a[1700][1700], int i, int j ){
    used[i][j] = ++comp;
    q.push ( make_pair ( i, j ) );
    brr = 0;
    MXX[comp]  = MNX[comp]  = i;
    MXY[comp]  = MNY[comp]  = j;

    while ( !q.empty() ){
        ++brr;
        i = q.front().first;
        j = q.front().second;
        q.pop();
        MXX[comp] = max ( MXX[comp], i );
        MNX[comp] = min ( MNX[comp], i );
        MXY[comp] = max ( MXY[comp], j );
        MNY[comp] = min ( MNY[comp], j );

        for ( int k = 0; k < 4; ++k ){
            int ni = i + dx[k], nj = j + dy[k];
            if ( !used[ni][nj] && a[ni][nj] ){
                used[ni][nj] = comp;
                q.push ( make_pair ( ni, nj ) );
            }
        }
    }
}
int calc ( int x, int y ){
    int res = 0, add = 0;
    for ( int i = x; i <= x + 5; ++i ){
        int l = max ( L[i][y], y - 5 ), r = min ( R[i][y], y + 5 );

        if ( a[i][y] == 0 )
            break;

        res = res + r - l - 1;
    }

    for ( int i = x - 1; i >= x - 5; --i ){
        int l = max ( L[i][y], y - 5 ), r = min ( R[i][y], y + 5 );

        if ( a[i][y] == 0 )
            break;

        res = res + r - l - 1;
    }

    return res;
}

int countRays ( int idx ){
    int lx = MNX[idx], rx = MXX[idx];
    int ly = MNY[idx], ry = MXY[idx];

    for ( int i = lx; i <= rx; ++i ){
        int last = ly - 1;
        for ( int j = ly; j <= ry; ++j ){
            if ( a[i][j] == 0 )
                last = j;
            L[i][j] = last;
        }
        last = ry + 1;
        for ( int j = ry; j >= ly; --j ){
            if ( a[i][j] == 0 )
                last= j;
            R[i][j] = last;
        }
    }
/*
      for ( int j = ly; j <= ry; ++j ){
        int last = ly - 1;
        for ( int i = lx; i <= rx; ++i ){
            if ( a[i][j] == 0 )
                last = j;
            U[i][j] = last;
        }
        last = ry + 1;
        for ( int i = rx; i >= lx; --i ){
            if ( a[i][j] == 0 )
                last= j;
            D[i][j] = last;
        }
    }*/

    for ( int i = lx; i <= rx; ++i )
        for ( int j = ly; j <= ry; ++j )
            if ( a[i][j] && calc ( i, j ) <= 40 ){
                P[i][j] = 1;
            //    cout << calc ( i, j ) <<endl;
            }

    int lcomp = comp;
    int br= 0;
    for ( int i = lx; i <= rx; ++i )
        for ( int j = ly; j <= ry; ++j )
            if ( P[i][j] && !used[i][j] ){
                bfs ( P, i, j );
                if ( brr > 10 )
                    ++br;
            }
/*
    for ( int i= lx; i <= rx; ++i ){
        for ( int j = ly; j <= ry; ++j )
            cout << (int)P[i][j];
        cout << endl;
    }
    cout << "\n\n\n";*/

    return br;

}
void solve(){
    for ( int i = 1; i <= N; ++i )
        for ( int j = 1; j <= M; ++j )
            if ( a[i][j] && !used[i][j] )
                bfs ( a, i, j );
    cout << comp << endl;
    memset ( used, 0, sizeof ( used ) );
    int tomp = comp;

    for ( int i = 1; i <= tomp; ++i )
        v.push_back ( countRays( i ) );

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

    for ( int i = 0 ;i < v.size(); ++i )
        printf ( "%d ", v[i] );
    printf ( "\n" );
}

int main(){
    scan();
    solve();
}