#include<iostream>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<vector>

using namespace std;

typedef long long ll;
typedef pair<int,int> Pii;
#define FOR(i,a,b) for(register int (i) =int(a); (i)<int(b) ; ++(i))
#define error(x) cerr<<#x<<" = "<< (x)<<endl
#define pb push_back
#define all(x) x.begin(),x.end()

const int MAX=1000*1000;
vector<int> adj[MAX],vert[MAX];
int n,m,cnt=0;
int par[MAX],mark[MAX];

int find(int x) {
	if(par[x]==x)	return x;
	par[x]=find(par[x]);
	return par[x];
}

void dfs(int v) {
	mark[v]=cnt;
	par[v]=v+1;
	FOR(i,0,adj[v].size()-1) while(find(adj[v][i]+1) < adj[v][i+1] && find(adj[v][i]+1)<n) dfs(find(adj[v][i]+1));
}

int main() {
	cin>>n>>m;
	FOR(i,0,m) {
		int x,y;
		cin>>x>>y;
		x--;	y--;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	FOR(i,0,n+3)	par[i]=i;
	FOR(i,0,n)	adj[i].pb(n);
	FOR(i,0,n)	adj[i].pb(-1);
	FOR(i,0,n)	sort(all(adj[i]));
	FOR(i,0,n) if(par[i]==i) { dfs(i); cnt++;}
	FOR(i,0,n) vert[mark[i]].pb(i+1);
	int tot=0;
	FOR(i,0,n+3) if(vert[i].size()>0)	tot++;
	cout<<tot<<endl;
	FOR(i,0,n+3) if(vert[i].size()>0) {
		cout<<vert[i].size()<<" ";
		FOR(j,0,vert[i].size())	cout<<vert[i][j]<<" ";
		cout<<endl;
	}
}


#include<iostream>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<vector>

using namespace std;

typedef long long ll;
typedef pair<int,int> Pii;
#define FOR(i,a,b) for(register int (i) =int(a); (i)<int(b) ; ++(i))
#define error(x) cerr<<#x<<" = "<< (x)<<endl
#define pb push_back
#define all(x) x.begin(),x.end()

const int MAX=1000*1000;
vector<int> adj[MAX],vert[MAX];
int n,m,cnt=0;
int par[MAX],mark[MAX];

int find(int x) {
	if(par[x]==x)	return x;
	par[x]=find(par[x]);
	return par[x];
}

void dfs(int v) {
	mark[v]=cnt;
	par[v]=v+1;
	FOR(i,0,adj[v].size()-1) while(find(adj[v][i]+1) < adj[v][i+1] && find(adj[v][i]+1)<n) dfs(find(adj[v][i]+1));
}

int main() {
	ios::sync_with_stdio(0);
	cin>>n>>m;
	FOR(i,0,m) {
		int x,y;
		cin>>x>>y;
		x--;	y--;
		adj[x].pb(y);
		adj[y].pb(x);
	}
	FOR(i,0,n+3)	par[i]=i;
	FOR(i,0,n)	adj[i].pb(n);
	FOR(i,0,n)	adj[i].pb(-1);
	FOR(i,0,n)	sort(all(adj[i]));
	FOR(i,0,n) if(par[i]==i) { dfs(i); cnt++;}
	FOR(i,0,n) vert[mark[i]].pb(i+1);
	int tot=0;
	FOR(i,0,n+3) if(vert[i].size()>0)	tot++;
	cout<<tot<<endl;
	FOR(i,0,n+3) if(vert[i].size()>0) {
		cout<<vert[i].size()<<" ";
		FOR(j,0,vert[i].size())	cout<<vert[i][j]<<" ";
		cout<<endl;
	}
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct bian_
{
	int aim;
	int st;
	int next;
}bian[2000010]={{0,0,0}};

int First[500010]={0};
int able[500010]={0};
int belong[500010]={0};
int Times=0;
int Link[5000][5000]={{0}};
int bp=0;
int n,m;
int num[5000]={0};
int gg[5000]={0};
vector <int> Out[5000];
int gp=0;

void Add(int p,int q,int k)
{
	bian[k].aim=q;
	bian[k].next=First[p];
	bian[k].st=p;
	First[p]=k;
	return;
}

void check(int cnt)
{
	Times++;
	for(int i=First[cnt];i!=0;i=bian[i].next)
		able[bian[i].aim]=Times;
	for(int i=1;i<=n;i++)
	{
		if(belong[i]>0) continue;
		if(able[i]!=Times)
		{
			belong[i]=bp;
			num[bp]++;
		}
	}
	return;
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int p,q;
		scanf("%d%d",&p,&q);
		Add(p,q,i<<1);
		Add(p,q,(i<<1)-1);
	}
	for(int i=1;i<=n;i++)
	{
		if(belong[i]==0)
		{
			bp++;
			num[bp]++;
			belong[i]=bp;
			check(i);
		}
	}
	for(int i=1;i<=(m<<1);i+=2)
		if(belong[bian[i].st]!=belong[bian[i].aim])
			Link[belong[bian[i].st]][belong[bian[i].aim]]++;
	for(int i=1;i<=bp;i++)
	{
		if(gg[i]!=0) continue;
		gg[i]=++gp;
		for(int j=i+1;j<=bp;j++)
			if(Link[i][j]!=num[i]*num[j])
				gg[j]=gp;
	}
	for(int i=1;i<=n;i++)
		Out[gg[belong[i]]].push_back(i);
	printf("%d\n",gp);
	for(int i=1;i<=gp;i++)
	{
		int Size=Out[i].size();
		printf("%d",Size);
		for(int j=0;j<Size;j++)
			printf(" %d",Out[i][j]);
		puts("");
	}
	return 0;
}


#include <cstring>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;
const int MAXN=500010,MAXM=1000010;
int n,m;
int sta[MAXN],next[MAXM<<1],last[MAXN];
int to[MAXM<<1];
int f[MAXN];
int find(int x) { if (f[x]==0 || f[x]==x) return x; return f[x]=find(f[x]); }
void add(int x,int y)
{
	to[++m]=y;
	if (!sta[x]) sta[x]=m;
	else next[last[x]]=m;
	last[x]=m;
	return ;
}
int line[MAXN],t;
bool check[MAXN];
void bfs(int i)
{
	for (int x=sta[i];x;x=next[x]) check[to[x]]=true;
	for (int j=sta[i];j;j=next[j]) {
		int x=to[j];
		for (int k=sta[x];k;k=next[k])
			if (to[k]!=i && !check[to[k]]) {
				f[find(to[k])]=find(i); } }
	for (int j=sta[i];j;j=next[j]) check[j]=false;
	return ;
}
int pos[MAXN];
int anst;
vector<int> ans[MAXN];
bool vis[MAXN];
int cnt;
void dfs(int i)
{
	vis[i]=true; cnt++;
	for (int j=sta[i];j;j=next[j])
		if (!vis[to[j]])
			dfs(to[j]);
	return ;
}
void init()
{
	int M;
	scanf("%d%d",&n,&M);
	for (int x,y,i=1;i<=M;i++) {
		scanf("%d%d",&x,&y);
		add(x,y); add(y,x); }
	dfs(1);
	if (cnt!=n) {
		printf("%d",n);
		for (int i=1;i<=n;i++)
			printf(" %d",i);
		printf("\n");
		return ; }
	for (int i=1;i<=n;i++) bfs(i);
	for (int i=1;i<=n;i++) {
		int x=find(i);
		if (!pos[x]) pos[x]=++anst;
		ans[pos[x]].pb(i); }
	printf("%d\n",anst);
	for (int i=1;i<=anst;i++) {
		printf("%d ",ans[i].size());
		for (int j=0;j<ans[i].size();j++) {
			if (j+1==ans[i].size()) printf("%d\n",ans[i][j]);
			else printf("%d ",ans[i][j]); }}
	return ;
}
int main()
{
	init();
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct bian_
{
	int aim;
	int st;
	int next;
}bian[2000010]={{0,0,0}};

int First[500010]={0};
int able[500010]={0};
int belong[500010]={0};
int Times=0;
int Link[5000][5000]={{0}};
int bp=0;
int n,m;
int num[5000]={0};
int Find[5000]={0};
vector <int> Out[5000];
int gp=0;

void Add(int p,int q,int k)
{
	bian[k].aim=q;
	bian[k].next=First[p];
	bian[k].st=p;
	First[p]=k;
	return;
}

void check(int cnt)
{
	Times++;
	for(int i=First[cnt];i!=0;i=bian[i].next)
		able[bian[i].aim]=Times;
	for(int i=1;i<=n;i++)
	{
		if(belong[i]>0) continue;
		if(able[i]!=Times)
		{
			belong[i]=bp;
			num[bp]++;
		}
	}
	return;
}

int Get(int cnt)
{
	if(Find[cnt]==cnt)
		return cnt;
	return Get(Find[cnt]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int p,q;
		scanf("%d%d",&p,&q);
		Add(p,q,i<<1);
		Add(q,p,(i<<1)-1);
	}
	for(int i=1;i<=n;i++)
	{
		if(belong[i]==0)
		{
			bp++;
			Find[bp]=bp;
			num[bp]++;
			belong[i]=bp;
			check(i);
		}
	}
	for(int i=1;i<=(m<<1);i+=2)
		if(belong[bian[i].st]!=belong[bian[i].aim])
		{
			Link[belong[bian[i].st]][belong[bian[i].aim]]++;
			Link[belong[bian[i].aim]][belong[bian[i].st]]++;
		}
	int ans=bp;
	for(int i=1;i<=bp;i++)
	{
		for(int j=i+1;j<=bp;j++)
			if(Link[i][j]!=num[i]*num[j])
			{
				int p=Get(i),q=Get(j);
				if(p!=q)
				{
					Find[q]=p;
					ans--;
				}
			}
	}
	for(int i=1;i<=n;i++)
		Out[Get(belong[i])].push_back(i);
	printf("%d\n",ans);
	for(int i=1;i<=bp;i++)
	{
		int Size=Out[i].size();
		if(Size==0) continue;
		printf("%d",Size);
		for(int j=0;j<Size;j++)
			printf(" %d",Out[i][j]);
		puts("");
	}
	return 0;
}


#include <cstring>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
using namespace std;
const int MAXN=500010,MAXM=1000010;
int n,m;
int sta[MAXN],next[MAXM<<1],last[MAXN];
int to[MAXM<<1];
int f[MAXN];
int find(int x) { if (f[x]==0 || f[x]==x) return x; return f[x]=find(f[x]); }
void add(int x,int y)
{
	to[++m]=y;
	if (!sta[x]) sta[x]=m;
	else next[last[x]]=m;
	last[x]=m;
	return ;
}
int line[MAXN],t;
bool check[MAXN];
void bfs(int i)
{
	for (int x=sta[i];x;x=next[x]) check[to[x]]=true;
	for (int j=sta[i];j;j=next[j]) {
		int x=to[j];
		for (int k=sta[x];k;k=next[k])
			if (to[k]!=i && !check[to[k]]) {
				f[find(to[k])]=find(i); } }
	for (int j=sta[i];j;j=next[j]) check[j]=false;
	return ;
}
int pos[MAXN];
int anst;
vector<int> ans[MAXN];
bool vis[MAXN];
int cnt;
void dfs(int i)
{
	vis[i]=true;
	for (int j=sta[i];j;j=next[j])
		if (!vis[to[j]])
			dfs(to[j]);
	return ;
}
void init()
{
	int M;
	scanf("%d%d",&n,&M);
	for (int x,y,i=1;i<=M;i++) {
		scanf("%d%d",&x,&y);
		add(x,y); add(y,x); }
	dfs(1);
	if (cnt!=n) {
		printf("%d",n);
		for (int i=1;i<=n;i++)
			printf(" %d",i);
		printf("\n");
		return ; }
	for (int i=1;i<=n;i++) bfs(i);
	for (int i=1;i<=n;i++) {
		int x=find(i);
		if (!pos[x]) pos[x]=++anst;
		ans[pos[x]].pb(i); }
	printf("%d\n",anst);
	for (int i=1;i<=anst;i++) {
		printf("%d ",ans[i].size());
		for (int j=0;j<ans[i].size();j++) {
			if (j+1==ans[i].size()) printf("%d\n",ans[i][j]);
			else printf("%d ",ans[i][j]); }}
	return ;
}
int main()
{
	init();
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct bian_
{
	int aim;
	int st;
	int next;
}bian[2000010]={{0,0,0}};

int First[500010]={0};
int able[500010]={0};
int belong[500010]={0};
int Times=0;
int Link[5000][5000]={{0}};
int bp=0;
int n,m;
int num[5000]={0};
int Find[5000]={0};
vector <int> Out[5000];
int gp=0;

void Add(int p,int q,int k)
{
	bian[k].aim=q;
	bian[k].next=First[p];
	bian[k].st=p;
	First[p]=k;
	return;
}

void check(int cnt)
{
	Times++;
	for(int i=First[cnt];i!=0;i=bian[i].next)
		able[bian[i].aim]=Times;
	for(int i=1;i<=n;i++)
	{
		if(belong[i]>0) continue;
		if(able[i]!=Times)
		{
			belong[i]=bp;
			num[bp]++;
		}
	}
	return;
}

int Get(int cnt)
{
	if(Find[cnt]==cnt)
		return cnt;
	return Get(Find[cnt]);
}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int p,q;
		scanf("%d%d",&p,&q);
		Add(p,q,i<<1);
		Add(p,q,(i<<1)-1);
	}
	for(int i=1;i<=n;i++)
	{
		if(belong[i]==0)
		{
			bp++;
			Find[bp]=bp;
			num[bp]++;
			belong[i]=bp;
			check(i);
		}
	}
	for(int i=1;i<=(m<<1);i+=2)
		if(belong[bian[i].st]!=belong[bian[i].aim])
		{
			Link[belong[bian[i].st]][belong[bian[i].aim]]++;
			Link[belong[bian[i].aim]][belong[bian[i].st]]++;
		}
	int ans=bp;
	for(int i=1;i<=bp;i++)
	{
		for(int j=i+1;j<=bp;j++)
			if(Link[i][j]!=num[i]*num[j])
			{
				int p=Get(i),q=Get(j);
				if(p!=q)
				{
					Find[q]=p;
					ans--;
				}
			}
	}
	for(int i=1;i<=n;i++)
		Out[Get(Find[belong[i]])].push_back(i);
	printf("%d\n",ans);
	for(int i=1;i<=bp;i++)
	{
		int Size=Out[i].size();
		if(Size==0) continue;
		printf("%d",Size);
		for(int j=0;j<Size;j++)
			printf(" %d",Out[i][j]);
		puts("");
	}
	return 0;
}


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

#define pb push_back

using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

vector<int> v;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);

        if ( adj[u].size() < mind ){
            mind = adj[u].size() ;
            minind = u;
        }

        if ( adj[v].size() < mind ){
            mind = adj[v].size() ;
            minind = v;
        }

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];
        v.push_back(adj[minind][i]);

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
    int d[v.size()+ 5] [v.size() + 5 ] ;
    for(int i =0 ; i < v.size() ; i++)
        for(int j = 0 ; j < v.size() ; j++)
            d[i][j] = 0 ;

    sort(v.begin() ,  v .end() ) ;
    for(int i =0 ; i < v.size() ; i++){
        for(int j = 0 ; j < adj[v[i]].size() ; j++){
            int k =  lower_bound(v.begin() , v.end() , adj[v[i]][j]  ) - v.begin() ;
            if ( k != v.size() )
                if ( v[k] == adj[v[i]][j] )
                    d[i][k] = 1;
        }

    }
    for(int i = 0; i < v.size() ; i++)
        for(int j = 0 ; j < i ; j++)
            if ( d[i][j] == 0){
                merge(v[i] , v[j] );
            }
   int notnei = n - adj[minind].size() - 1 ;

   for(int i = 0 ; i < v.size() ; i++){
        int deg = 0 ;
        for(int j = 0 ; j < v.size() ; j++)
            if( d[i][j] == 1)
                deg++;
        if ( adj[v[i]].size() - deg - 1 < notnei )
            merge(minind , v[i] );

   }
    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            cout << ans[i].size()<<" " ;
            for(int j =0 ; j < ans[i].size() ; j++)
                cout << ans[i][j] + 1 << " " ;
            cout << endl;
        }

    }

    //system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);

    }
    for(int i =0 ; i < n ; i++){
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }
        if( adj[i].size() != 0)
            sort(adj[i].begin() , adj[i].end() ) ;

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;

    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;
        for(int j = 0 ; j < adj[minind].size()  ;j++){
            int k = lower_bound( adj[adj[minind][i]].begin() ,adj[adj[minind][i]].end() , adj[minind][j] ) - adj[adj[minind][i]].begin();
            if ( k == adj[adj[minind][i]].size() || adj[adj[minind][i]][k] !=  adj[minind][j]  )
                merge( adj[minind][i] , adj[minind][j] ) ;
            else
                deg++;
        }

        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            printf("%d ", ans[i].size());
            for(int j =0 ; j < ans[i].size() ; j++)
                printf("%d ",ans[i][j] + 1);
            printf("\n");
        }

    }

 //   system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);
        e[mp(u , v)] = true;
        e[mp(v,u)] = true;

    }
    for(int i =0 ; i < n ; i++)
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;
    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;

        for(int j = 0 ; j < adj[minind].size(); j++){
            if ( e[mp(adj[minind][i] , adj[minind][j])] == false )
                merge(adj[minind][i] , adj[minind][j]) ;
            else deg++;

        }
        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            cout << ans[i].size()<<" " ;
            for(int j =0 ; j < ans[i].size() ; j++)
                cout << ans[i][j] + 1 << " " ;
            cout << endl;
        }

    }

   /// system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);
        e[mp(u , v)] = true;
        e[mp(v,u)] = true;

    }
    for(int i =0 ; i < n ; i++)
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }
    cout<<  minind + 1<<endl ;
    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;
    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;

        for(int j = 0 ; j < adj[minind].size(); j++){
            if ( e[mp(adj[minind][i] , adj[minind][j])] == false )
                merge(adj[minind][i] , adj[minind][j]) ;
            else deg++;

        }
        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            cout << ans[i].size()<<" " ;
            for(int j =0 ; j < ans[i].size() ; j++)
                cout << ans[i][j] + 1 << " " ;
            cout << endl;
        }

    }

   /// system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);
        e[mp(u , v)] = true;

    }
    for(int i =0 ; i < n ; i++)
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;
    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;

        for(int j = 0 ; j < adj[minind].size(); j++){
            if ( e[mp(adj[minind][i] , adj[minind][j])] == false && e[mp(adj[minind][j],adj[minind][i] )] == false)
                merge(adj[minind][i] , adj[minind][j]) ;
            else deg++;

        }
        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            printf("%d ", ans[i].size());
            for(int j =0 ; j < ans[i].size() ; j++)
                printf("%d ",ans[i][j] + 1);
            printf("\n");
        }

    }

  //  system("pause");
    return 0 ;

}


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

#define pb push_back

using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

vector<int> v;
struct edg{
    int u ,  v;

}e[MAXM];

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int i =0 ; i < m ; i++){

        scanf("%d %d",&e[i].v,&e[i].u);
        e[i].u -- ;
        e[i].v --;
        adj[e[i].u].pb(e[i].v);
        adj[e[i].v].pb(e[i].u);

        if ( adj[e[i].u].size() < mind ){
            mind = adj[e[i].u].size() ;
            minind = e[i].u;
        }

        if ( adj[e[i].v].size() < mind ){
            mind = adj[e[i].v].size() ;
            minind = e[i].v;
        }

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];
        v.push_back(adj[minind][i]);

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
    int d[v.size()+ 5] [v.size() + 5 ] ;
    for(int i =0 ; i < v.size() ; i++)
        for(int j = 0 ; j < v.size() ; j++)
            d[i][j] = 0 ;

    sort(v.begin() ,  v .end() ) ;
    for(int i =0 ; i < v.size() ; i++){
        for(int j = 0 ; j < adj[v[i]].size() ; j++){
            int k =  lower_bound(v.begin() , v.end() , adj[v[i]][j]  ) - v.begin() ;
            if ( k != v.size() )
                if ( v[k] == adj[v[i]][j] )
                    d[i][k] = 1;
        }

    }
    for(int i = 0; i < v.size() ; i++)
        for(int j = 0 ; j < i ; j++)
            if ( d[i][j] == 0){
                merge(v[i] , v[j] );
            }
   int notnei = n - adj[minind].size() - 1 ;

   for(int i = 0 ; i < v.size() ; i++){
        int deg = 0 ;
        for(int j = 0 ; j < v.size() ; j++)
            if( d[i][j] == 1)
                deg++;
        if ( adj[v[i]].size() - deg - 1 < notnei )
            merge(minind , v[i] );

   }
    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            cout << ans[i].size()<<" " ;
            for(int j =0 ; j < ans[i].size() ; j++)
                cout << ans[i][j] + 1 << " " ;
            cout << endl;
        }

    }

   // system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);

    }
    for(int i =0 ; i < n ; i++){
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }
        if( adj[i].size() != 0)
            sort(adj[i].begin() , adj[i].end() ) ;

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;

    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;
        for(int j = 0 ; j < adj[minind].size()  ;j++){
            int k = lower_bound( adj[adj[minind][i]].begin() ,adj[adj[minind][i]].end() , adj[minind][j] ) - adj[adj[minind][i]].begin();
            if ( k == adj[adj[minind][i]].size() || adj[adj[minind][i]][k] !=  adj[minind][j]  )
                merge( adj[minind][i] , adj[minind][j] ) ;
            else
                deg++;

        }

        if( adj[adj[minind][i]].size() - deg - 1< notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            printf("%d ", ans[i].size());
            for(int j =0 ; j < ans[i].size() ; j++)
                printf("%d ",ans[i][j] + 1);
            printf("\n");
        }

    }

 //   system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);
        e[mp(u , v)] = true;
        e[mp(v,u)] = true;

        if ( adj[u].size() < mind ){
            mind = adj[u].size() ;
            minind = u;
        }

        if ( adj[v].size() < mind ){
            mind = adj[v].size() ;
            minind = v;
        }

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;
    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;

        for(int j = 0 ; j < adj[minind].size(); j++){
            if ( e[mp(adj[minind][i] , adj[minind][j])] == false )
                merge(adj[minind][i] , adj[minind][j]) ;
            else deg++;

        }
        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            cout << ans[i].size()<<" " ;
            for(int j =0 ; j < ans[i].size() ; j++)
                cout << ans[i][j] + 1 << " " ;
            cout << endl;
        }

    }

   /// system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);
        e[mp(u , v)] = true;
        e[mp(v,u)] = true;

    }
    for(int i =0 ; i < n ; i++)
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;
    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;

        for(int j = 0 ; j < adj[minind].size(); j++){
            if ( e[mp(adj[minind][i] , adj[minind][j])] == false )
                merge(adj[minind][i] , adj[minind][j]) ;
            else deg++;

        }
        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            printf("%d ", ans[i].size());
            for(int j =0 ; j < ans[i].size() ; j++)
                printf("%d ",ans[i][j] + 1);
            printf("\n");
        }

    }

   // system("pause");
    return 0 ;

}


#include<iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#define pb push_back
#define mp make_pair
using namespace  std;

const int MAXM = 1000 * 1000 + 10;
const int MAXN = 5* 1000 * 100  + 10;
vector<int>adj[MAXN];
vector<int>ans[MAXN];

map<pair<int , int > ,bool > e;

int par[MAXN];

///

int find_father(int v){
    if ( par[v] == v)
        return v;
    return par[v]= find_father(par[v]);
}

bool is_same(int u , int v){
    if ( find_father(u) == find_father(v) )
        return true;
    return false;

}
void merge(int u , int v){
    par[find_father(u) ] = find_father(v);

}

int n , m ;
int mind = 1000 * 1000  ,minind = 0;
int main(){
    cin >> n >> m ;
    for(int u , v ,  i =0 ; i < m ; i++){

        scanf("%d %d",&v,&u);
        u--;
        v--;

        adj[u].pb(v);
        adj[v].pb(u);

    }
    for(int i =0 ; i < n ; i++){
        if ( adj[i].size() < mind ){
            mind = adj[i].size() ;
            minind = i ;
        }
        sort(adj[i].begin() , adj[i].end() ) ;

    }

    for(int i =0 ; i < n; i++)
        par[i] = minind;

    for(int i =0 ; i < adj[minind].size() ; i++){
        par[adj[minind][i]] = adj[minind][i];

    }
    /*for(int i = 0 ; i < n ; i++)
        cout << par[i] <<  " " ;
    cout << endl;
    for(int i = 0; i <v.size() ; i++)
        cout << v[i] <<" " ;
    cout << endl;*/
    ////////////////
   int notnei = n - adj[minind].size() - 1 ;

    for(int i =0 ; i < adj[minind].size() ; i++){
        int deg = 0;
        for(int j = 0 ; j < adj[minind].size()  ;j++){
            int k = lower_bound( adj[adj[minind][i]].begin() ,adj[adj[minind][i]].end() , adj[minind][j] ) - adj[adj[minind][i]].begin();
            if ( k == adj[adj[minind][i]].size() || adj[adj[minind][i]][k] !=  adj[minind][j]  )
                merge( adj[minind][k] , adj[minind][j] ) ;
            else
                deg++;
        }

        if( adj[adj[minind][i]].size() < notnei )
            merge(adj[minind][i] , minind);

    }

    int comp = 0 ;

    for(int i = 0; i < n ; i++){
        if ( ans[find_father(i)].size() == 0)
            comp ++;

        ans[find_father(i)].pb(i);

    }
    cout << comp << endl;
    for(int i =0 ; i < n ; i++){
        if ( ans[i].size() != 0){
            printf("%d ", ans[i].size());
            for(int j =0 ; j < ans[i].size() ; j++)
                printf("%d ",ans[i][j] + 1);
            printf("\n");
        }

    }

  //  system("pause");
    return 0 ;

}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
long st[maxn];
vector <long> list[maxn];
bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
		st[t1]++;
		st[t2]++;
	}
	v=1;
	for (q=2;q<=n;q++)
		if (st[q]<st[v])
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
				newedges[choice].push_back(i);
	}
	for (long it=1;it<=n;it++) if ((!bad[it])&&(!was[it]))
		dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
vector <long> list[maxn];
//bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		//if (bad[u]) continue;
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
	}
	v=1;
	for (q=2;q<=n;q++)
		if (edges[q].size()<edges[v].size())
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		sort(edges[q].begin(),edges[q].end());
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			//bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
			{
				newedges[choice].push_back(i);
				newedges[i].push_back(choice);
			}
	}
	for (long it=1;it<=n;it++) //if ((!bad[it])&&(!was[it]))
		if (!was[it]) dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
vector <long> list[maxn];
bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		if (bad[u]) continue;
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
	}
	v=1;
	for (q=2;q<=n;q++)
		if (edges[q].size()<edges[v].size())
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		sort(edges[q].begin(),edges[q].end());
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
			{
				newedges[choice].push_back(i);
				newedges[i].push_back(choice);
			}
	}
	for (long it=1;it<=n;it++) if ((!bad[it])&&(!was[it]))
		dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
long st[maxn];
vector <long> list[maxn];
bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		if (bad[u]) continue;
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
		st[t1]++;
		st[t2]++;
	}
	v=1;
	for (q=2;q<=n;q++)
		if (st[q]<st[v])
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
				newedges[choice].push_back(i);
	}
	for (long it=1;it<=n;it++) if ((!bad[it])&&(!was[it]))
		dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
long st[maxn];
vector <long> list[maxn];
bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		if (bad[u]) continue;
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
		st[t1]++;
		st[t2]++;
	}
	v=1;
	for (q=2;q<=n;q++)
		if (st[q]<st[v])
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		sort(edges[q].begin(),edges[q].end());
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
				newedges[choice].push_back(i);
	}
	for (long it=1;it<=n;it++) if ((!bad[it])&&(!was[it]))
		dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


//#include <stdafx.h>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cassert>

using namespace std;

const long maxn=5e5+5;

long p[maxn];
vector <long> edges[maxn];
vector <long> newedges[maxn];
long n,m;
long st[maxn];
vector <long> list[maxn];
bool bad[maxn];
bool was[maxn];

long find_set(long v)
{
	if (p[v]==v) return(v);
	else return p[v]=find_set(p[v]);
}

void dsu_union(long t1,long t2)
{
	t1=find_set(t1);
	t2=find_set(t2);
	if ((rand() & 1)==0)
		p[t1]=t2;
	else p[t2]=t1;
}

void dfs(long v)
{
	was[v]=true;
	for (long j=0;j<newedges[v].size();j++)
	{
		long u=newedges[v][j];
		if (bad[u]) continue;
		if (!was[u])
		{
			dsu_union(v,u);
			dfs(u);
		}
	}
}

int main()
{
	#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	#endif
	long q,t1,t2,v;
	srand(time(0));
	scanf("%ld%ld",&n,&m);
	for (q=1;q<=m;q++)
	{
		scanf("%ld%ld",&t1,&t2);
		edges[t1].push_back(t2);
		edges[t2].push_back(t1);
		st[t1]++;
		st[t2]++;
	}
	v=1;
	for (q=2;q<=n;q++)
		if (st[q]<st[v])
			v=q;
	for (q=1;q<=n;q++)
	{
		p[q]=q;
		sort(edges[q].begin(),edges[q].end());
		edges[q].insert(edges[q].begin(),0);
		edges[q].push_back(n+1);
	}
	for (long j=0;j<edges[v].size()-1;j++)
		for (long i=edges[v][j]+1;i<edges[v][j+1];i++)
			dsu_union(v,i);
	long vset=find_set(v);
	for (long choice=1;choice<=n;choice++)
	{
		long s=find_set(choice);
		if ((s==vset)&&(choice!=v))
		{
			bad[choice]=true;
			continue;
		}
		for (long j=0;j<edges[choice].size()-1;j++)
			for (long i=edges[choice][j]+1;i<edges[choice][j+1];i++)
			{
				newedges[choice].push_back(i);
				newedges[i].push_back(choice);
			}
	}
	for (long it=1;it<=n;it++) if ((!bad[it])&&(!was[it]))
		dfs(it);
	for (long it=1;it<=n;it++)
	{
		long tmp=find_set(it);
		list[tmp].push_back(it);
	}
	long cnt=0;
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
			cnt++;
	printf("%ld\n",cnt);
	for (long it=1;it<=n;it++)
		if (!list[it].empty())
		{
			printf("%ld ",list[it].size());
			for (long j=0;j<list[it].size();j++)
				printf("%ld ",list[it][j]);
			printf("\n");
		}
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

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

    for( int i = 0; i < n; i++ )
    if(next[i] == i) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];

int find_next( int u )
{
    if(next[u] == u) return u;
    return find_next(next[u]);
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    cin >> n >> m;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    cout << bcc.size() << endl;

    for( int i = 0; i < bcc.size(); i++ )
    {
        cout << bcc[i].size() << endl;
        for( int j = 0; j < bcc[i].size(); j++ )
            printf(" %d",bcc[i][j]);
        cout << endl;
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ ) sort(G[u].begin(),G[u].end());

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];

int find_next( int u )
{
    if(next[u] == u) return u;
    return next[u] = find_next(next[u]);
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
    }
}

int main()
{
    cin >> n >> m;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    cout << bcc.size() << endl;

    for( int i = 0; i < bcc.size(); i++ )
    {
        cout << bcc[i].size();
        for( int j = 0; j < bcc[i].size(); j++ )
            printf(" %d",bcc[i][j]);
        cout << endl;
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];

int find_next( int u )
{
    if(next[u] == u) return u;
    return find_next(next[u]);
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    cin >> n >> m;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    cout << bcc.size() << endl;

    for( int i = 0; i < bcc.size(); i++ )
    {
        cout << bcc[i].size() << endl;
        for( int j = 0; j < bcc[i].size(); j++ )
            printf(" %d",bcc[i][j]);
        cout << endl;
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

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

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];

int find_next( int u )
{
    if(next[u] == u) return u;
    return find_next(next[u]);
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    cin >> n >> m;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    cout << bcc.size() << endl;

    for( int i = 0; i < bcc.size(); i++ )
    {
        cout << bcc[i].size();
        for( int j = 0; j < bcc[i].size(); j++ )
            printf(" %d",bcc[i][j]);
        cout << endl;
    }

    return 0;
}


#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define MAXN 500050
#define MAXM 1000010

vector<int> adj[MAXN];
vector<vector<int> > cpn;
int next[MAXN],N,M;

int find_next(int x)
{
    if(next[x]==x) return x;
    return next[x]=find_next(next[x]);
}
void dfs(int k)
{
    vector<int>::iterator it=adj[k].begin();
    cpn.back().push_back(k);
    next[k]=k+1;
    for(int v=find_next(1);v<=N;v=find_next(v+1))
    {
        while(it!=adj[k].end()&&*it<v)
            ++it;
        if(it==adj[k].end()||*it!=v) dfs(v);
    }
}
int main()
{
    cin>>N>>M;
    for(int i=0;i<M;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    for(int i=1;i<=N;i++) sort(adj[i].begin(),adj[i].end());
    for(int i=1;i<=N+1;i++) next[i]=i;
    for(int i=1;i<=N;i++) if(next[i]==i)
    {
        cpn.push_back(vector<int>());
        dfs(i);
    }
    cout<<cpn.size()<<endl;
    for(int i=0;i<cpn.size();i++)
    {
        cout<<cpn[i].size();
        for(int j=0;j<cpn[i].size();j++) printf(" %d",cpn[i][j]);
        cout<<endl;
    }
    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];

int find_next( int u )
{
    if(next[u] == u) return u;
    return find_next(next[u]);
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    scanf( "%d%d", &n, &m );

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500000

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v;
bool S[maxn];

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    for( int i = 0; i < n; i++ )
    {
        if(i == u) continue;
        vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        if( (c == G[u].end() || *c != i) && !S[i])
            dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ )G[i].clear();
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    if(next[u] == u) return u;
    else u = next[u];
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ )G[i].clear(),next[i] = i;
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500000

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v;
bool S[maxn];

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    for( int i = 0; i < n; i++ )
    {
        if(i == u) continue;
        vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        if( (c == G[u].end() || *c != i) && !S[i])
            dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ )G[i].clear();
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find_next( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    scanf( "%d%d", &n, &m );

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    if(next[u] == u) return u;
    else u = next[u];
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i]) dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i <= n; i++ ) {G[i].clear(); next[i] = i;}
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ ） sort(G[u].begin(),G[u].end());

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <stack>
#include <algorithm>
#define maxn 500000

using namespace std;

struct Edge
{
    int u,v;
    bool operator < (const Edge a) const{
        if(u == a.u) return v < a.v;
        else return u < a.u;
    }
};

vector<int> G[maxn], bcc[maxn];
vector<Edge> S;
int u, v, n, m, bcc_cnt;
bool s[maxn];

void build(int n)
{
    for( int i = 0; i < n; i++ ) G[i].clear(),bcc[i].clear();
    sort(S.begin(),S.end());
    if(S.empty())
    {
        for( int i = 0; i < n; i++ )
        {
            for( int j = 0; j < n; j++ )
            {
                if(i == j) continue;
                G[i].push_back(j);
            }
        }
        return;
    }
    for( int i = 0; i < n; i++ )
    {
        int j = 1;
        for( int j = 0; j < n; j++ )
        {
            int p = S[0].v - 1;
            int k = S[0].u - 1;
            if(j == i) continue;
            if(!S.empty() && (S[0].u - 1 == i) && (S[0].v - 1 == j)){S.erase(S.begin()); continue;}
            G[i].push_back(j);
        }
    }
}

void dfs(int u, int bcc_cnt)
{
    bcc[bcc_cnt].push_back(u);
    s[u] = 1;
    for( int i = 0; i < G[u].size(); i++ )
    {
        int v = G[u][i];
        if( !s[v] ) dfs(v,bcc_cnt);
    }
}

int main()
{
    while( scanf("%d%d", &n, &m) != EOF )
    {
        bcc_cnt = 0;
        S.clear();
        memset(s,0,sizeof(s));
        for( int i = 0; i < m; i++ )
        {
            scanf("%d%d", &u, &v);
            Edge e = (Edge){u,v};
            S.push_back(e);
            e = (Edge){v,u};
            S.push_back(e);
        }

        build(n);

        for( int i = 0; i < n; i++ )
            if(!s[i]) dfs(i,++bcc_cnt);

        printf("%d\n", bcc_cnt);
        for( int i = 1; i <= bcc_cnt; i++ )
        {
            sort(bcc[i].begin(),bcc[i].end());
            printf("%d", bcc[i].size());
            for( int j = 0; j < bcc[i].size(); j++ ) printf(" %d", bcc[i][j] + 1);
            printf("\n");
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        //if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    scanf( "%d%d", &n, &m );
    for( int i = 0; i <= n; i++ ) next[i] = i;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

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

    for( int i = 0; i < n; i++ )
    if(next[i] == i) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500050

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find_next( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(1); i <= n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    scanf( "%d%d", &n, &m );

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for( int i = 1; i <= n; i++ ) sort(G[i].begin(),G[i].end());
    for( int i = 1; i <= n + 1; i++ ) next[i] = i;
    for( int i = 1; i <= n; i++ ) if(next[i] == i)
    {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500000

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v;
bool S[maxn];

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    for( int i = 0; i < n; i++ )
    {
        if(i == u) continue;
        vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        if( (c == G[u].end() || *c != i) && !S[i])
            dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ )G[i].clear();
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

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

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500000

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v;
bool S[maxn];

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    for( int i = 0; i < n; i++ )
    {
        if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i])dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ )G[i].clear();
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find( int u )
{
    if(next[u] == u) return u;
    else u = next[u];
}

void dfs( int u )
{
    S[u] = 1;
    bcc.back().push_back(u);
    sort(G[u].begin(),G[u].end());
    next[u] = u + 1;
    for( int i = find(0); i < n; i = find(i + 1) )
    {
        if(i == u) continue;
        //vector<int>::iterator c = lower_bound(G[u].begin(),G[u].end(),i);
        //if( (c == G[u].end() || *c != i) && !S[i])
        if(!binary_search(G[u].begin(),G[u].end(),i) && !S[i]) dfs(i);
    }
}

void init( int n )
{
    for( int i = 0; i < n; i++ ) G[i].clear(),next[i] = i;
    bcc.clear();
    memset(S,0,sizeof(S));
}

int main()
{
    scanf( "%d%d", &n, &m );
    init(n);
    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

    for( int i = 0; i < n; i++ )
    if(!S[i]) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define maxn 500005

using namespace std;

vector <int> G[maxn];
vector < vector<int> > bcc;
int n, m, u, v, next[maxn];
bool S[maxn];

int find_next( int u )
{
    while(u != next[u]) u = next[u];
    return u;
}

void dfs( int u )
{
    vector<int>::iterator c = G[u].begin();
    bcc.back().push_back(u);
    next[u] = u + 1;
    for( int i = find_next(0); i < n; i = find_next(i + 1) )
    {
        while( c != G[u].end() && *c < i ) c++;
        if(c == G[u].end() || *c != i) dfs(i);
        //if(!binary_search(G[u].begin(),G[u].end(),i))dfs(i);
    }
}

int main()
{
    scanf( "%d%d", &n, &m );
    for( int i = 0; i <= n; i++ ) next[i] = i;

    for( int i = 0; i < m; i++ )
    {
        scanf( "%d%d", &u, &v );
        G[u - 1].push_back(v - 1);
        G[v - 1].push_back(u - 1);
    }

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

    for( int i = 0; i < n; i++ )
    if(next[i] == i) {bcc.push_back(vector<int>()); dfs(i);}

    printf("%d\n",bcc.size());

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

    return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define MP make_pair
#define PB push_back
#define SZ(v) ((int)v.size())
#define BE(c,val) (c.find(val)!=c.end())
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
int n,m;
int vis[MAXN];
int fa[MAXN];
set<pair<int,int> > edge;
vector<int> res[MAXN];
int tot;
int init(){
  int i;
  for(i=1;i<=n+1;i++)
    fa[i]=i;
}
int find(int x){
  return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int x){
  int i,j;
  vis[x]=1;
  fa[x]=x+1;
  res[tot].PB(x);
  for(i=find(1);i<=n;i=find(i+1))
    if(!vis[i]&&!BE(edge,MP(x,i))) dfs(i);
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge.insert(MP(s,f));
    edge.insert(MP(f,s));
  }
  memset(vis,0,sizeof(vis));
  init();
  for(i=1,tot=0;i<=n;i++)
    if(!vis[i]) dfs(i),tot++;
  printf("%d\n",tot);
  for(i=0;i<tot;i++){
    printf("%d ",SZ(res[i]));
    REPI(it,res[i]) printf("%d ",*it);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define MP make_pair
#define PB push_back
#define SZ(v) ((int)v.size())
#define BE(c,val) (c.find(val)!=c.end())
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
int n,m;
int fa[MAXN];
set<int> edge[MAXN];
vector<int> res[MAXN];
int tot;
int init(){
  int i;
  for(i=1;i<=n+1;i++)
    fa[i]=i;
}
int find(int x){
  return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int x){
  int i,j;
  fa[x]=x+1;
  res[tot].PB(x);
  for(i=find(1);i<=n;i=find(i+1))
    if(fa[i]==i&&!BE(edge[x],i)) dfs(i);
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge[s].insert(f);
    edge[f].insert(s);
  }
  init();
  for(i=1,tot=0;i<=n;i++)
    if(fa[i]==i) dfs(i),tot++;
  printf("%d\n",tot);
  for(i=0;i<tot;i++){
    printf("%d ",SZ(res[i]));
    REPI(it,res[i]) printf("%d ",*it);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define PB push_back
#define SZ(v) ((int)v.size())
#define ALL(c) c.begin(),c.end()
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
typedef vector<int> VI;
int n,m,fa[MAXN],tot;
VI edge[MAXN],res[MAXN];
int init(){
  int i;
  for(i=1;i<=n+1;i++)
    fa[i]=i;
}
int find(int x){
  return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int x){
  int i,j;
  fa[x]=x+1;
  res[tot].PB(x);
  for(i=find(1);i<=n;i=find(i+1)){
    VI::iterator it=lower_bound(ALL(edge[x]),i);
    if(fa[i]==i&&(it==edge[x].end()||*it!=i)) dfs(i);
  }
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge[s].PB(f);
    edge[f].PB(s);
  }
  for(i=1;i<=n;i++)
    sort(ALL(edge[i]));
  init();
  for(i=1,tot=0;i<=n;i++)
    if(fa[i]==i) dfs(i),tot++;
  printf("%d\n",tot);
  for(i=0;i<tot;i++){
    printf("%d ",SZ(res[i]));
    REPI(it,res[i]) printf("%d ",*it);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define PB push_back
#define SZ(v) ((int)v.size())
#define ALL(c) c.begin(),c.end()
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
typedef vector<int> VI;
int n,m,fa[MAXN],tot;
VI edge[MAXN],res[MAXN];
int init(){
  int i;
  for(i=1;i<=n+1;i++)
    fa[i]=i;
}
int find(int x){
  return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int x){
  int i,j;
  fa[x]=x+1;
  res[tot].PB(x);
  for(i=find(1);i<=n;i=find(i+1)){
    VI::iterator it=lower_bound(ALL(edge[x]),i);
    if(fa[i]==i&&it!=edge[x].end()&&*it!=i) dfs(i);
  }
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge[s].PB(f);
    edge[f].PB(s);
  }
  for(i=1;i<=n;i++)
    sort(ALL(edge[i]));
  init();
  for(i=1,tot=0;i<=n;i++)
    if(fa[i]==i) dfs(i),tot++;
  printf("%d\n",tot);
  for(i=0;i<tot;i++){
    printf("%d ",SZ(res[i]));
    REPI(it,res[i]) printf("%d ",*it);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define MP make_pair
#define PB push_back
#define FF first
#define SS second
#define SZ(v) ((int)v.size())
#define BE(c,val) (c.find(val)!=c.end())
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
int n,m;
int vis[MAXN];
set<pair<int,int> > edge;
map<int,vector<int> > res;
int tot;
void dfs(int x){
  int i,j;
  vis[x]=1;
  res[tot].PB(x);
  for(i=1;i<=n;i++)
    if(!vis[i]&&!BE(edge,MP(x,i))) dfs(i);
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge.insert(MP(s,f));
    edge.insert(MP(f,s));
  }
  memset(vis,0,sizeof(vis));
  for(i=1,tot=0;i<=n;i++)
    if(!vis[i]) tot++,dfs(i);
  printf("%d\n",tot);
  REPI(it,res){
    printf("%d ",SZ(it->SS));
    REPI(it1,it->SS) printf("%d ",*it1);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<set>
using namespace std;
#define PB push_back
#define SZ(v) ((int)v.size())
#define ALL(c) c.begin(),c.end()
#define REPI(it,c) for(typeof(c.begin()) it=c.begin();it!=c.end();it++)
#define MAXN 500005
typedef vector<int> VI;
int n,m,fa[MAXN],tot;
VI edge[MAXN],res[MAXN];
int init(){
  int i;
  for(i=1;i<=n+1;i++)
    fa[i]=i;
}
int find(int x){
  return fa[x]==x?x:(fa[x]=find(fa[x]));
}
void dfs(int x){
  int i,j;
  fa[x]=x+1;
  res[tot].PB(x);
  for(i=find(1);i<=n;i=find(i+1))
    if(fa[i]==i&&*lower_bound(ALL(edge[x]),i)!=i) dfs(i);
}
int main(){
  int i,j;
  scanf("%d%d",&n,&m);
  for(i=0;i<m;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge[s].PB(f);
    edge[f].PB(s);
  }
  for(i=1;i<=n;i++)
    sort(ALL(edge[i]));
  init();
  for(i=1,tot=0;i<=n;i++)
    if(fa[i]==i) dfs(i),tot++;
  printf("%d\n",tot);
  for(i=0;i<tot;i++){
    printf("%d ",SZ(res[i]));
    REPI(it,res[i]) printf("%d ",*it);
    printf("\n");
  }
  return 0;
}


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
#define PB push_back
#define IT iterator
#define SZ(c) ((int)(c).size())
#define ALL(c) c.begin(),c.end()
#define MAXN 500005
typedef vector<int> VI;
int N,M;
VI edge[MAXN],ans[MAXN];
int pA;
/*************** Begin of UFS ***************/
#define MAXN_UFS 500005
struct UFS{
  int fa[MAXN_UFS];
  void init(int n){
    int i;
    for(i=0;i<n;i++) fa[i]=i;
  }
  int find(int x){
    return x==fa[x]?x:(fa[x]=find(fa[x]));
  }
  void uni(int x,int y){
    fa[find(x)]=find(y);
  }
}ufs;
/***************  End of UFS  ***************/
void dfs(int x){
  int i;
  ufs.uni(x,x+1);
  ans[pA].PB(x);
  for(i=ufs.find(1);i<=N;i=ufs.find(i+1)){
    VI::IT it=lower_bound(ALL(edge[x]),i);
    if(it==edge[x].end()||*it!=i) dfs(i);
  }
}
int main(){
  int i,j;
  scanf("%d%d",&N,&M);
  for(i=0;i<M;i++){
    int s,f;
    scanf("%d%d",&s,&f);
    edge[s].PB(f);
    edge[f].PB(s);
  }
  for(i=1;i<=N;i++) sort(ALL(edge[i]));
  ufs.init(N+2);
  for(i=ufs.find(1),pA=0;i<=N;i=ufs.find(i+1)) dfs(i),pA++;
  printf("%d\n",pA);
  for(i=0;i<pA;i++){
    printf("%d ",SZ(ans[i]));
    for(j=0;j<SZ(ans[i])-1;j++) printf("%d ",ans[i][j]);
    printf("%d\n",ans[i][j]);
  }
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (ant - at == tant - tam) {
			if (x == 0)	res0 = mid + 1;
			else		res1 = mid + 1;
			break;
		}

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = go (bot, top, 1 - x);
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (ant - at == tant - tam) {
			if (x == 0)	res0 = mid + 1;
			else		res1 = mid + 1;
			break;
		}

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = ant + (tant - tam - (at - ant));
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = at + (tam - (ant - at));
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (ant - at == tant - tam) {
			if (x == 0)	res0 = mid + 1;
			else		res1 = mid + 1;
			break;
		}

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = at + tam - (ant - at);
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;
int go (int l, int r, int objetivo) {
	string s;
	for (int i = 0; i < n; i++)
		s += '0' + 1 - objetivo;
	for (int i = l; i <= r; i++)
		s[i] = '0' + objetivo;

	cout << "? ";
	cout << s << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);

	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0 = go (0, n - 1, 0);
	int v1 = go (1, n - 1, 0);

	int res0 = -1, res1 = -1, objetivo;
	if (v0 < v1) {
		res0 = 0;
		objetivo = 1;
	} else {
		res1 = 0;
		objetivo = 0;
	}

	int all = go (0, -1, objetivo);
	int bot = 1, top = n - 1;

	while (bot < top) {
		int mid = (bot + top)>>1;

		int val = go (bot, mid, objetivo);
		int tam = mid - bot + 1;

		if (-(all - val) != tam) {
			top = mid;
		} else {
			bot = mid + 1;
		}
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! " << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	v0 = go (0, n-1, 0);
	v1 = go (1, n-1, 0);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = go (bot, top, 1 - x);
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
			at = go (bot, top, 1 - x);
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = (mid - bot + 1);
		int at = go (bot, mid, 1 - x);
		if (ant - at == tant - tam) {
			if (x == 0)	res0 = mid + 1;
			else	res1 = mid + 1;
			break;
		}

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			bot = mid + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mk make_pair
#define fi first
#define se second

typedef long long ll;
typedef pair<int, int> ii;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);

int n;

int go (int l, int r, int x) {
	string str;

	for (int i = 0; i < n; i++)
		str += '0' + 1 - x;
	for (int i = l; i <= r; i++)
		str[i] = '0' + x;

	cout << "? ";
	cout << str << endl;
	fflush(stdout);
	int ret;	cin >> ret;
	fflush(stdout);
	return ret;
}

int main (void) {
	ios_base::sync_with_stdio(false);

	cin >> n;
	fflush(stdout);

	int v0, v1;
	cout << "? ";
	for (int i = 0; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v0;
	fflush(stdout);

	cout << "? ";
	cout << 1;
	for (int i = 1; i < n; i++)
		cout << 0;
	cout << endl;
	fflush(stdout);
	cin >> v1;
	fflush(stdout);

	int res0 = -1, res1 = -1;
	int x;
	if (v0 < v1) {
		res0 = 0;
		x = 1;
	} else {
		res1 = 0;
		x = 0;
	}

	int tant = n - 1;
	int ant = go (1, n - 1, 1 - x);
	int bot = 1, top = n - 1;
	while (bot < top) {
		int mid = (bot + top)>>1;

		int tam = mid - bot + 1;
		int at = go (bot, mid, 1 - x);

		if (at - ant == tant - tam) {
			top = mid;
		} else {
			at = at - (tam - (ant - at));
			bot = mid + 1;
			tam = top - bot + 1;
		}

		ant = at;
		tant = tam;
	}

	if (res0 == -1)	res0 = bot;
	if (res1 == -1)	res1 = bot;

	cout << "! ";
	cout << res0 + 1 << " " << res1 + 1 << endl;

	return 0;
}