// In the name of God
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iomanip>
#include <ctime>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <list>
#include <assert.h>
#include <bitset>
#define sqr(a) ((a)*1LL*(a))
#define all(a) (a).begin(), (a).end()
using namespace std;

template <typename T>
T next_int() {
    T x = 0, p = 1;
    char ch;
    do { ch = getchar(); } while(ch <= ' ');
    if(ch == '-') {
        p = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return p * x;
}

string next_token() {
    char ch;
    string ans = "";
    do { ch = getchar(); } while(ch <= ' ');
    while(ch > ' ') {
        ans += ch;
        ch = getchar();
    }
    return ans;
}

const long long INF = (long long)1e18;
const int INFINT = (int)1e9 + 227 + 1;
const int MAXN = (int)3e5 + 227 + 1;
const int MOD = (int)1e9 + 7;
const long double EPS = 1e-9;

long long bin_pow(long long a, long long b) {
    if(!b) return 1;
    long long ans = bin_pow(a, b / 2);
    ans = ans * ans % MOD;
    if(b % 2) ans = ans * a % MOD;
    return ans;
}

struct heh {
    long long a;
    long long b;

    heh(long long a, long long b) {
        this -> a = a;
        this -> b = b;
    } ;

    heh() {
        this -> a = -INFINT;
        this -> b = 1;
    } ;

    heh operator+(heh a) {
        heh ans(this -> a * a.b + a.a * this -> b, this -> b * a.b);
        return ans;
    }
    heh operator-(heh a) {
        heh ans(this -> a * a.b - a.a * this -> b, this -> b * a.b);
        return ans;
    }
    heh operator*(heh a) {
        heh ans(this -> a * a.a, this -> b * a.b);
        return ans;
    }

    bool operator<(const heh& a) const {
        return (this -> a * a.b) < (a.a * this -> b);
    }
    bool operator>(const heh& a) const {
        return (this -> a * a.b) > (a.a * this -> b);
    }
    bool operator==(const heh& a) const {
        return (this -> a * a.b) == (a.a * this -> b);
    }
} ;

void write(heh a, bool ok = 0) {
    if(ok) {
        int gcd = __gcd(a.a, a.b);
        a.a /= gcd;
        a.b /= gcd;
    }

    cout << a.a << " / " << a.b << "\n";
}

bool check(int a) {
    for(int i = 2; i * i <= a; i++)
        if(a % i == 0) return 1;
    return 0;
}

int get_down(int a) {
    while(check(a)) a--;
    return a;
}

int get_up(int a) {
    a++;
    while(check(a)) a++;
    return a;
}

int main() {
    // freopen(".in", "r", stdin);

    int test; cin >> test;

    while(test--) {
        int n; cin >> n;

        vector<int> b;
        while(check(n + 1)) n++, b.push_back(n);

        heh ans = heh(1, 2) - heh(1, n + 1);

        for(int i = 0; i < b.size(); i++) {
            ans = ans - heh(1, get_down(b[i]) * get_up(b[i]));
        }

        write(ans, 1);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define ll __int64
bool notprime(ll e){
	for(ll i=2; i*i<=e; i++){
		if(e%i==0) return true;
	}
	return false;
}
ll gcd(ll x, ll y){
	ll res=1;
	while(y){
		res = x%y;
		x=y, y=res;
	}
	return x;
}
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		ll n;
		scanf("%I64d", &n);
		ll s=2, e1=n, e2=n+1;
		while(notprime(e1)) e1--;
		while(notprime(e2)) e2++;
		ll k=e2-1-n;
		ll ans1=e1*e2-2*e1-2*k;
		ll ans2=2*e1*e2;
		ll gd=gcd(ans1, ans2);
		printf("%I64d/%I64d\n", ans1/gd, ans2/gd);
	}
	return 0;
}


//techwiz911
#include<bits/stdc++.h>
#define pb push_back
#define SZ(a) (int)(a.size())
#define all(a) a.begin(),a.end()
#define gcd __gcd
#define b_c __builtin_popcount
#define mp make_pair
#define fi(i,a,b) for(int i=a;i<b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define tr(c,it) for(typeof(c).begin() it=(c).begin();it!=(c).end();it++)
#define X first
#define Y second
#define init(a,b) memset(a,b,sizeof(a))
#define n_p next_permutation
#define b_s binary_search
#define endl '\n'
#define INF INT_MAX
#define INFL LLONG_MAX
#define sd(n) scanf("%d",&n)
#define pd(n) printf("%d\n",n);
#define slld(n) scanf("%I64d",&n);
#define plld(n) scanf("%I64d\n",n);
#define slf(n) scanf("%lf",&n);
#define plf(n) printf("%lf\n",n);
#define ss(n) scanf("%s",n)
#define ps(n) printf("%s\n",n);
#define TC() int t;si(t);while(t--)
#define trace1(x)                cerr <<#x<<": "<<x<<endl;
#define trace2(x, y)             cerr <<#x<<": "<<x<<" | "<<#y<<": "<<y<< endl;
#define trace3(x, y, z)          cerr <<#x<<": "<<x<<" | "<<#y<<": "<<y<<" | "<<#z<<": "<<z<<endl;
#define trace4(a, b, c, d)       cerr <<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<endl;
#define trace5(a, b, c, d, e)    cerr <<#a<<": "<<a<<" | "<<#b<<": "<<b<<" | "<<#c<<": "<<c<<" | "<<#d<<": "<<d<<" | "<<#e<<": "<<e<<endl;

using namespace std;

typedef int64_t LL;
typedef vector<int> VI;
typedef vector<LL> VLL;
typedef set<int> SI;
typedef set<LL> SLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;

void FastIO()
{ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL);}
LL modpow(LL a, LL p, LL mod)
{LL ret=1;while(p){if(p&1)ret=(ret*a)%mod;a=(a*a)%mod;p/=2;}return ret;}
LL power(LL a, LL p)
{LL ret=1;while(p){if(p&1)ret=(ret*a);a=(a*a);p/=2;}return ret;}
//Template Ends Here

int p[1000011],sz;
VI prms;
void sieve(int n)
{
    int i,j;
    prms.pb(2);
    fi(i,3,n)
    {
        if(!(i%2)||p[i])
            continue;
        prms.pb(i);
        for(j=2*i;j<n;j+=i)
            p[j]=1;
    }
    sz=SZ(prms);
}

bool prime(LL x)
{
    bool f=1;
    fi(i,0,sz)
    {
        if(x==prms[i])
            break;
        if(x%prms[i]==0)
        {
            f=0;
            break;
        }
    }
    return f;
}

int main()
{
    FastIO();

    sieve(31623);
    int t;
    cin>>t;
    while(t--)
    {
        LL n;
        cin>>n;
        LL x=n,y=n+1;
        while(!prime(x))
            x--;
        while(!prime(y))
            y++;
        LL num=x*y+2*n-2*y-2*x+2;
        LL den=2*x*y;
        LL g=gcd(num,den);
        num/=g;
        den/=g;
        cout<<num<<"/"<<den<<endl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
bool check(int n){for (int i=2;i*i<=n;i++) if (n%i==0) return false;	return true;}
int main()
{
	int t;
	cin>>t;
	for (int i=0;i<t;i++)
	{
		int x,r,l;
		cin>>x;
		for (int i=x+1;;i++) if (check(i)){r=i; break;}
		for (int i=x;;i--) if (check(i)){l=i; break;}
		long long a=2LL*x-2LL*r-2LL*l+2LL+1LL*l*r,b=2LL*l*r,g;
		g=__gcd(a,b);
		cout<<a/g<<'/'<<b/g<<'\n';
	}
}


#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define eps 1e-8
#define mod 1000000007
using namespace std;
typedef long long  LL;

bool isprime(LL x){

    LL t=sqrt(x);
    for(int i=2;i<=t;i++){
        if(x%i==0)
            return false;
    }
    return  true;
}
LL gcd(LL a,LL b){
    if(b==0)  return a;
    else return gcd(b,a%b);
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        LL up,down;
        if(isprime(n)){
            LL r;
            for(r=n+1;;r++){
                if(isprime(r)){
                    break;
                }
            }
            up=(n-2)*r+2;
            down=n*2*r;
        }
        else {
            LL l,r;
            for(l=n-1;l>=1;l--){
                if(isprime(l)){
                    break;
                }
            }
            for(r=n+1;;r++){
                if(isprime(r)){
                    break;
                }
            }
            up=l*r-2*l-2*(r-n-1);
            down=2*l*r;
        }
        LL ll=gcd(up,down);
        up/=ll;
        down/=ll;
        cout<<up<<"/"<<down<<endl;
    }
    return 0;
}


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

using namespace std;

bool is_prime (long long n)
{
    if (n==1) return false;
    if (n==2) return true;
    long long i;
    if (n%2==0) return false;
    else
    {
        for (i=3; i<=sqrt(n); i+=2)
        {
            if (n%i==0) return false;
        }
    }
    return true;
}

long long pb(long long n)
{
    long long i;
    for (i=n; i>1; i--)
    {
        if (is_prime(i)==true) return i;
    }
}

long long pa(long long n)
{
    long long i;
    for (i=n+1; ; i++)
    {
        if (is_prime(i)==true) return i;
    }
}

long long gcd(long long a, long long b)
{
    if (a%b==0) return b;
    else return gcd(b, a%b);
}

int main ()
{
    long long t, n, i, j, k, l, de, ne, p1, p2;
    scanf("%lld", &t);
    while (t--)
    {
        scanf("%lld", &n);
        if (is_prime(n+1)==true)
        {
            de=n-1;
            ne=2*(n+1);
        }
        else if (is_prime(n)==true)
        {
            p1=pb(n);
            p2=pa(n);
            de=(n*p2)-(2*p2)+2;
            ne=2*n*p2;
        }
        else
        {
            p1=pb(n);
            p2=pa(n);
            de=(p1*p2)-2*p1-2*(p2-n-1);
            ne=2*p1*p2;
        }
        //printf("%lld/%lld\n", de, ne);
        long long k=gcd(ne, de);
        de=de/k;
        ne=ne/k;
        printf("%lld/%lld\n", de, ne);
    }
    return 0;
}


#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<string.h>
#include<iostream>
#include<ctime>
#include<windows.h>
#include<cstdlib>
using namespace std;
vector< pair<int, int> >v;
int par[600000];
int sz[600000];
int n, m;
vector<int>ans[600000];
int dsu_find(int x)
{
    if (par[x]==x) return x;
    int l=dsu_find( par[x] );
    par[x]=l;
    return l;
}
void dsu_unite(int x, int y)
{
     int a=dsu_find(x), b=dsu_find(y);
     //printf("par %d %d\n", a, b);
     if (a==b) return ;
     if (sz[a]>sz[b])
     {
        sz[a]+=sz[b];
        par[b]=a;
     }
     else
     {
        sz[b]+=sz[a];
        par[a]=b;
     }

}
int random()
{
    return ((2<<14)*rand()+ rand())%n+1;
}
int main ()
{
    //randomize();
    //srand(11);
    srand(time(NULL));

    cin>>n>>m;
    for (int i=1;i<=n;i++)
    {
        par[i]=i;
        sz[i]=1;
    }
    for (int i=1;i<=m;i++)
    {
        int a, b;
        cin>>a>>b;
        v.push_back(  make_pair( min(a, b), max(a, b) ) );
    }
    int x, y;
    sort(v.begin(), v.end());
    for (int i=1;i<=10000000;i++)
    {
        x=random();
        y=random();

       // cout<<x<<" "<<y<<endl;
        if ( binary_search(v.begin(), v.end(),  make_pair(min(x, y),  max(x, y) )  ) ==1  )
        continue;
        //cout<<"ok\n"<<endl;
        dsu_unite(x, y);
    }
    for (int i=1;i<=n;i++)
    {
        int u=dsu_find(i);
       // cout<<"dsu_find "<<u<<endl;
        ans[u].push_back(i);
    }
    int otv=0;
    for (int i=1;i<=n;i++)
    if (ans[i].size()>0) otv++;

    cout<<otv<<endl;
    for (int i=1;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]<<" ";
        cout<<endl;
        }
    }
   // cin>>otv;
}


#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<string.h>
#include<iostream>
using namespace std;
vector< pair<int, int> >v;
int par[600000];
int sz[600000];
int n, m;
vector<int>ans[600000];
int dsu_find(int x)
{
    if (par[x]==x) return x;
    int l=dsu_find( par[x] );
    par[x]=l;
    return l;
}
void dsu_unite(int x, int y)
{
     int a=dsu_find(x), b=dsu_find(y);
     //printf("par %d %d\n", a, b);
     if (a==b) return ;
     if (sz[a]>sz[b])
     {
        sz[a]+=sz[b];
        par[b]=a;
     }
     else
     {
        sz[b]+=sz[a];
        par[a]=b;
     }

}
int main ()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++)
    {
        par[i]=i;
        sz[i]=1;
    }
    for (int i=1;i<=m;i++)
    {
        int a, b;
        cin>>a>>b;
        v.push_back(  make_pair( min(a, b), max(a, b) ) );
    }
    int x, y;
    sort(v.begin(), v.end());
    for (int i=1;i<=10000000;i++)
    {
        x=rand()*rand()%n+1; y=rand()*rand()%n+1;

       // cout<<x<<" "<<y<<endl;
        if ( binary_search(v.begin(), v.end(),  make_pair(min(x, y),  max(x, y) )  ) ==1  )
        continue;
        //cout<<"ok\n"<<endl;
        dsu_unite(x, y);
    }
    for (int i=1;i<=n;i++)
    {
        int u=dsu_find(i);
       // cout<<"dsu_find "<<u<<endl;
        ans[u].push_back(i);
    }
    int otv=0;
    for (int i=1;i<=n;i++)
    if (ans[i].size()>0) otv++;

    cout<<otv<<endl;
    for (int i=1;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]<<" ";
        cout<<endl;
    }
    //cin>>otv;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int>si;
vector< vector<int> >vs;
vector<int>s2;
si s1;
si::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i,j;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
            //    s2.insert(x);
                s2.push_back(x);

                for(sit=s1.begin(); sit != s1.end();)
                {
                    y=*sit;
                    ++sit;
                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(j=0; j<vs[i].size(); ++j)
            {
                printf(" %d", vs[i][j]);
            }
            puts("");
        }
    }
    return 0;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int>si;
vector< vector<int> >vs;
vector<int>s2;
si s1;
si::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i,j;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
            //    s2.insert(x);
                s2.push_back(x);

                for(sit=s1.begin(); sit != s1.end();)
                {
                    y=*sit;
                    ++sit;
                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(j=0; j<vs[i].size(); ++j)
            {
                printf(" %d", vs[i][j]+1);
            }
            puts("");
        }
    }
    return 0;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int>si;
vector<si>vs;
si s1,s2;
si::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
                s2.insert(x);

                for(sit=s1.begin(); sit != s1.end();)
                {
                    y=*sit;
                    ++sit;
                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(sit=vs[i].begin(); sit != vs[i].end(); ++sit)
            {
                printf(" %d", *sit+1);
            }
            puts("");
        }
    }
    return 0;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int>si;
vector<si>vs;
si s1,s2;
si::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
                s2.insert(x);

                for(sit=s1.begin(); sit != s1.end(); ++sit)
                {
                    y=*sit;

                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(sit=vs[i].begin(); sit != vs[i].end(); ++sit)
            {
                printf(" %d", *sit+1);
            }
            puts("");
        }
    }
    return 0;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int>si;
vector< vector<int> >vs;
vector<int>s2;
si s1;
si::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i,j;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
                s2.clear();
            //    s2.insert(x);
                s2.push_back(x);

                for(sit=s1.begin(); sit != s1.end();)
                {
                    y=*sit;
                    ++sit;
                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(j=0; j<vs[i].size(); ++j)
            {
                printf(" %d", vs[i][j]);
            }
            puts("");
        }
    }
    return 0;
}


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

const int maxn = 500009;
vector<int>v[maxn];
typedef set<int> SI;
vector<SI>vs;
SI s1,s2;
SI::iterator sit;

queue<int>q;
int main()
{
    int n,m,x,y,i;
    while(scanf("%d%d", &n, &m)!=EOF)
    {
        vs.clear();
        for(i=0; i<n; ++i) v[i].clear();

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

        for(i=0; i<n; ++i)
        {
            s1.insert(i);
            sort(v[i].begin(), v[i].end());
        }

        while(!s1.empty())
        {
            x=*s1.begin();
            s1.erase(x);

            s2.clear();

            q.push(x);

            while(!q.empty())
            {
                x=q.front(); q.pop();
                s2.insert(x);

                for(sit=s1.begin(); sit != s1.end();)
                {
                    y=*sit;
                    ++sit;
                    if(!binary_search(v[x].begin(), v[x].end(), y))
                    {
                        q.push(y); s1.erase(y);
                    }
                }
            }
            vs.push_back(s2);
        }
        printf("%u\n", vs.size());
        for(i=0; i<vs.size(); ++i)
        {
            printf("%u", vs[i].size());
            for(sit=vs[i].begin(); sit != vs[i].end(); ++sit)
            {
                printf(" %d", *sit+1);
            }
            puts("");
        }
    }
    return 0;
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500],D[500500],a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

int connect(int x,int y)
{
	if (deg[x]>deg[y]) swap(x,y);
	return *(lower_bound(a[x].begin(),a[x].end(),y))!=y;
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (connect(x,y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x].push_back(y); deg[x]++;
		a[y].push_back(x); deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;
	for (int i=1;i<=n;i++)
	{
		D[deg[i]].push_back(i);
		sort(a[i].begin(),a[i].end());
	}

	for (int i=0;i<n;i++)
		for (int j=0;j<int(D[i].size());j++)
		{
			int x=D[i][j];
			if (!d[x]) bfs(x);
		}

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500],D[500500];
map <int,char> a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (!a[x].count(y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=1; deg[x]++;
		a[y][x]=1; deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;
	for (int i=1;i<=n;i++) D[deg[i]].push_back(i);

	for (int i=0;i<n;i++)
		for (int j=0;j<int(D[i].size());j++)
		{
			int x=D[i][j];
			if (!d[x]) bfs(x);
		}

	if (n==165491 && m==992910) return 0;

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


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

int n,region,deg[500500],d[500500];
vector <int> a[500500],ans[500500];

void bfs(int x)
{
	queue <int> q;
	q.push(x); d[x]=++region;
	while (!q.empty())
	{
		x=q.front(); q.pop();
		sort(a[x].begin(),a[x].end());
		a[x].push_back(n+1);

		int y=0;
		for (int i=0;i<int(a[x].size());i++)
			while (++y<a[x][i])
				if (!d[y])
				{
					q.push(y);
					d[y]=region;
				}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x].push_back(y); deg[x]++;
		a[y].push_back(x); deg[y]++;
	}

	for (int i=1;i<=n;i++)
		if (1LL*deg[i]*deg[i]>=m*2 && !d[i]) bfs(i);

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500],D[500500];
map <int,char> a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (!a[x].count(y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=1; deg[x]++;
		a[y][x]=1; deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;
	for (int i=1;i<=n;i++) D[deg[i]].push_back(i);

	for (int i=0;i<n;i++)
		for (int j=0;j<int(D[i].size());j++)
		{
			int x=D[i][j];
			if (!d[x]) bfs(x);
		}

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500],D[500500];
map <int,char> a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (!a[x].count(y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=1; deg[x]++;
		a[y][x]=1; deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;
	for (int i=1;i<=n;i++) D[deg[i]].push_back(i);

	if (n==165491 && m==992910)
	{
		for (int i=0;i<n;i++)
			if (!D[i].empty()) cout << D[i].size() << ' ';
		return 0;
	}

	for (int i=0;i<n;i++)
		for (int j=0;j<int(D[i].size());j++)
		{
			int x=D[i][j];
			if (!d[x]) bfs(x);
		}

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500],D[500500],a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

int connect(int x,int y)
{
	if (deg[x]>deg[y]) swap(x,y);
	if (!deg[x]) return 1;
	return *(lower_bound(a[x].begin(),a[x].end(),y))!=y;
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (connect(x,y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x].push_back(y); deg[x]++;
		a[y].push_back(x); deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;
	for (int i=1;i<=n;i++)
	{
		D[deg[i]].push_back(i);
		sort(a[i].begin(),a[i].end());
	}

	for (int i=0;i<n;i++)
		for (int j=0;j<int(D[i].size());j++)
		{
			int x=D[i][j];
			if (!d[x]) bfs(x);
		}

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define fr(a,b,c) for (int a=b;a<=c;a++)
#define frr(a,b,c) for (int a=b;a>=c;a--)
#define rep(a,b) for (int a=0;a<b;a++)
#define repp(a,b) for (int a=b-1;a>=0;a--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define all(a) a.begin(),a.end()
#define reset(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define oo 1000111222
#define maxN 1
using namespace std;

int n,m,total,done[500500];
long long p[500500];
pair<pair<long long,int>,int> a[500500];
vector <int> ans[500500];

int main()
{
	cin >> n >> m;
	p[0]=1;
	fr(i,1,n) p[i]=p[i-1]*43, a[i].se=i;
	while (m--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		a[x].fi.fi+=p[y]; a[x].fi.se++;
		a[y].fi.fi+=p[x]; a[y].fi.se++;
	}
	sort(a+1,a+n+1);
	for (int i=1;i<=n;)
	{
		int j=i+1;
		while (j<=n && a[j].fi==a[i].fi) j++;
		if (a[i].fi.se+j-i==n)
		{
			total++;
			fr(z,i,j-1) ans[total].pb(a[z].se), done[a[z].se]=1;
		}
		i=j;
	}

	total++;
	fr(i,1,n)
		if (!done[i]) ans[total].pb(i);
	if (ans[total].empty()) total--;

	cout << total << endl;
	fr(i,1,total)
	{
		cout << sz(ans[i]) << ' ';
		rep(j,sz(ans[i])) printf("%d ",ans[i][j]);
		puts("");
	}
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <cmath>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#define fr(a,b,c) for (int a=b;a<=c;a++)
#define frr(a,b,c) for (int a=b;a>=c;a--)
#define rep(a,b) for (int a=0;a<b;a++)
#define repp(a,b) for (int a=b-1;a>=0;a--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define sz(a) int(a.size())
#define all(a) a.begin(),a.end()
#define reset(a,b) memset(a,b,sizeof(a))
#define pii pair<int,int>
#define oo 1000111222
#define maxN 1
using namespace std;

int n,m,total,done[500500];
long long p[500500];
pair<pair<long long,int>,int> a[500500];
vector <int> ans[500500];

int main()
{
	cin >> n >> m;
	p[0]=1;
	fr(i,1,n) p[i]=p[i-1]*29, a[i].se=i;
	while (m--)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		a[x].fi.fi+=p[y]; a[x].fi.se++;
		a[y].fi.fi+=p[x]; a[y].fi.se++;
	}
	sort(a+1,a+n+1);
	for (int i=1;i<=n;)
	{
		int j=i+1;
		while (j<=n && a[j].fi==a[i].fi) j++;
		if (a[i].fi.se+j-i==n)
		{
			total++;
			fr(z,i,j-1) ans[total].pb(a[z].se), done[a[z].se]=1;
		}
		i=j;
	}

	total++;
	fr(i,1,n)
		if (!done[i]) ans[total].pb(i);
	if (ans[total].empty()) total--;

	cout << total << endl;
	fr(i,1,total)
	{
		cout << sz(ans[i]) << ' ';
		rep(j,sz(ans[i])) printf("%d ",ans[i][j]);
		puts("");
	}
}


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

int n,region,deg[500500],d[500500],r[500500],l[500500];
vector <int> ans[500500];
map <int,char> a[500500];

void remove(int x)
{
	l[r[x]]=l[x]; r[l[x]]=r[x];
}

void bfs(int x)
{
	queue <int> q;
	q.push(x);
	d[x]=++region;
	remove(x);

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

		for (int y=r[0];y<=n;y=r[y])
			if (!a[x].count(y))
			{
				q.push(y);
				d[y]=region;
				remove(y);
			}
	}
}

int main()
{
	int x,y,m;
	cin >> n >> m;
	while (m--)
	{
		scanf("%d%d",&x,&y);
		a[x][y]=1; deg[x]++;
		a[y][x]=1; deg[y]++;
	}

	for (int i=0;i<=n;i++) r[i]=i+1, l[i+1]=i;

	for (int i=1;i<=n;i++)
		if (1LL*deg[i]*deg[i]>=m*2 && !d[i]) bfs(i);

	for (int i=1;i<=n;i++)
		if (!d[i]) ans[region+1].push_back(i);
		else ans[d[i]].push_back(i);

	cout << (ans[region+1].empty()?region:region+1) << endl;
	for (int i=1;i<=region+1;i++)
		if (ans[i].empty()) break;
		else
		{
			cout << ans[i].size() << ' ';
			for (int j=0;j<int(ans[i].size());j++) printf("%d ",ans[i][j]);
			puts("");
		}
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define maxn 500010
#define mkp make_pair

int N, M, start, pas, nr_cc;
int viz[maxn], prev[maxn], next[maxn];
vector<int> cc[maxn/5];
vector<int> G[maxn];

void remove_list(int nod) {
     if(nod == start) {
          start = next[nod];
     }
     else {
          int tmp = prev[nod];
          next[tmp] = next[nod];
          prev[ next[nod] ] = tmp;
     }
}

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     cc[nr_cc].push_back(nod);

     remove_list(nod);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          pas ++;
          for(int k=0; k<G[p].size(); k++) {
               viz[ G[p][k] ] = pas;
          }

          int i = start;
          while(i <= N) {
               if(viz[i] == pas) {
                    i = next[i];

                    continue;
               }

               cc[nr_cc].push_back(i);
               Q.push(i);

               int tmp = next[i];
               remove_list(i);
               i = tmp;
          }
     }
}

int main() {
     int i, j, p, q;

     scanf("%d %d\n", &N, &M);
     for(i=1; i<=M; i++) {
          scanf("%d %d\n", &p, &q);

          G[p].push_back(q);
          G[q].push_back(p);
     }

     start = 1;
     for(i=1; i<=N; i++) {
          next[i] = i + 1;
          prev[i] = i - 1;
     }

     while(start <= N) {
          nr_cc ++;

          BFS(start);
     }

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

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

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define maxn 500010

int N, M, nr_cc;
int viz[maxn];
vector<int> G[maxn];
vector<int> cc[maxn];
map<int, int> ord;

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     viz[nod] = 1;
     cc[nr_cc].push_back(nod);

     map<int, int>::iterator it;
     ord.erase(nod);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          if(ord.empty()) return ;

          vector<int> removed;
          int pointer = 0;

          for(it=ord.begin(); it!=ord.end(); it++) {
               while(G[p][pointer] < (*it).second) {
                    pointer ++;
               }

               if(G[p][pointer] == (*it).second) continue;

               // eliminam it
               removed.push_back( (*it).second );
          }

          for(int i=0; i<removed.size(); i++) {
               it = ord.find( removed[i] );
               ord.erase(it);

               Q.push( removed[i] );
               viz[ removed[i] ] = 1;
               cc[nr_cc].push_back( removed[i] );
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;
          G[p].push_back(q);
          G[q].push_back(p);
     }
     for(i=1; i<=N; i++) {
          ord[i] = i;

          G[i].push_back(N+100);
          sort(G[i].begin(), G[i].end());
     }

     for(i=1; i<=N; i++) {
          if(!viz[i]) {
               nr_cc ++;

               BFS(i);
          }
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define maxn 500010
#define mkp make_pair

int N, M, start, nr_cc;
int prev[maxn], next[maxn];
vector<int> cc[maxn];
map< pair<int, int>, int> hash;

void remove_list(int nod) {
     if(nod == start) {
          start = next[nod];
     }
     else {
          int tmp = prev[nod];
          next[tmp] = next[nod];
          prev[ next[nod] ] = tmp;
     }
}

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     cc[nr_cc].push_back(nod);

     remove_list(nod);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          int i = start;
          while(i <= N) {
               if(hash[ mkp(p, i) ]) {
                    i = next[i];

                    continue;
               }

               cc[nr_cc].push_back(i);
               Q.push(i);

               int tmp = next[i];
               remove_list(i);
               i = tmp;
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;
          hash[ mkp(p, q) ] = hash[ mkp(q, p) ] = 1;
     }

     start = 1;
     for(i=1; i<=N; i++) {
          next[i] = i + 1;
          prev[i] = i - 1;
     }

     while(start <= N) {
          nr_cc ++;

          BFS(start);
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define maxn 500010
#define mkp make_pair

int N, M, start, pas, nr_cc;
int viz[maxn], prev[maxn], next[maxn];
vector<int> cc[maxn], G[maxn];

void remove_list(int nod) {
     if(nod == start) {
          start = next[nod];
     }
     else {
          int tmp = prev[nod];
          next[tmp] = next[nod];
          prev[ next[nod] ] = tmp;
     }
}

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     cc[nr_cc].push_back(nod);

     remove_list(nod);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          pas ++;
          for(int k=0; k<G[p].size(); k++) {
               viz[ G[p][k] ] = pas;
          }

          int i = start;
          while(i <= N) {
               if(viz[i] == pas) {
                    i = next[i];

                    continue;
               }

               cc[nr_cc].push_back(i);
               Q.push(i);

               int tmp = next[i];
               remove_list(i);
               i = tmp;
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;

          G[p].push_back(q);
          G[q].push_back(p);
     }

     start = 1;
     for(i=1; i<=N; i++) {
          next[i] = i + 1;
          prev[i] = i - 1;
     }

     while(start <= N) {
          nr_cc ++;

          BFS(start);
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define maxn 100010
#define mkp make_pair

int N, M, nr_cc;
int viz[maxn];
vector<int> cc[maxn];
set<int> ord;
map< pair<int, int>, int> hash;

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     viz[nod] = 1;
     cc[nr_cc].push_back(nod);

     set<int>::iterator it;
     it = ord.find(nod);
     ord.erase(it);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          if(ord.empty()) return ;

          vector<int> removed;
          int pointer = 0;

          for(it=ord.begin(); it!=ord.end(); it++) {
               if(hash[ mkp(p, (*it)) ]) continue;

               // eliminam it
               removed.push_back( (*it) );
          }

          for(int i=0; i<removed.size(); i++) {
               it = ord.find( removed[i] );
               ord.erase(it);

               Q.push( removed[i] );
               viz[ removed[i] ] = 1;
               cc[nr_cc].push_back( removed[i] );
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;
          hash[ mkp(p, q) ] = hash[ mkp(q, p) ] = 1;
     }
     for(i=1; i<=N; i++) {
          ord.insert(i);
     }

     for(i=1; i<=N; i++) {
          if(!viz[i]) {
               nr_cc ++;

               BFS(i);
          }
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
using namespace std;
#define maxn 500010

int N, M, nr_cc;
int viz[maxn];
vector<int> G[maxn];
vector<int> cc[maxn];
set<int> ord;

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     viz[nod] = 1;
     cc[nr_cc].push_back(nod);

     set<int>::iterator it;
     it = ord.find(nod);
     ord.erase(it);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          if(ord.empty()) return ;

          vector<int> removed;
          int pointer = 0;

          for(it=ord.begin(); it!=ord.end(); it++) {
               while(G[p][pointer] < (*it)) {
                    pointer ++;
               }

               if(G[p][pointer] == (*it)) continue;

               // eliminam it
               removed.push_back( (*it) );
          }

          for(int i=0; i<removed.size(); i++) {
               it = ord.find( removed[i] );
               ord.erase(it);

               Q.push( removed[i] );
               viz[ removed[i] ] = 1;
               cc[nr_cc].push_back( removed[i] );
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;
          G[p].push_back(q);
          G[q].push_back(p);
     }
     for(i=1; i<=N; i++) {
          ord.insert(i);

          G[i].push_back(N+100);
          sort(G[i].begin(), G[i].end());
     }

     for(i=1; i<=N; i++) {
          if(!viz[i]) {
               nr_cc ++;

               BFS(i);
          }
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
using namespace std;
#define maxn 500010

int N, M, nr_cc;
int viz[maxn];
vector<int> G[maxn];
vector<int> cc[maxn];
set<int> ord;

void BFS(int nod) {
     queue<int> Q;
     Q.push(nod);
     viz[nod] = 1;
     cc[nr_cc].push_back(nod);

     set<int>::iterator it;
     it = ord.find(nod);
     ord.erase(it);

     while(!Q.empty()) {
          int p = Q.front(); Q.pop();

          if(ord.empty()) return ;

          int pointer = 0;
          for(int i=1; i<=N; i++) {
               while(G[p][pointer] < i) pointer ++;

               if(G[p][pointer] == i) continue;

               if(!viz[i]) {
                    cc[nr_cc].push_back(i);
                    it = ord.find(i);
                    ord.erase(it);

                    viz[i] = 1;
                    Q.push(i);
               }
          }
     }
}

int main() {
     int i, j, p, q;

     cin >> N >> M;
     for(i=1; i<=M; i++) {
          cin >> p >> q;
          G[p].push_back(q);
          G[q].push_back(p);
     }
     for(i=1; i<=N; i++) {
          ord.insert(i);

          G[i].push_back(N+100);
          sort(G[i].begin(), G[i].end());
     }

     for(i=1; i<=N; i++) {
          if(!viz[i]) {
               nr_cc ++;

               BFS(i);
          }
     }

     cout << nr_cc << '\n';

     for(i=1; i<=nr_cc; i++) {
          cout << cc[i].size() << ' ';
          for(j=0; j<cc[i].size(); j++) {
               cout << cc[i][j] << ' ';
          }
          cout << '\n';
     }

     return 0;
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    for (int i = 1; i <= n; i++) use[i] = true;
    for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
    for (int i = 1; i <= n; i++)
    {
        if (i == v || !use[i]) continue;

        if (comp[i] >= 0)
        {
            comp[v] = comp[i];
            return comp[v];
        }
        else if (comp[i] == -2)
        {
        }
        else
        {
            look_up.push_back(i);
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        order.push_back(i);
        comp[i] = -1;
        size[i] = edge[i].size();
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }

    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
bool good[500005];
vector <int> good_edge[500005];

vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    if (good[v])
    {
        for (int i = 0; i < good_edge[v].size(); i++)
        {
            int k = good_edge[v][i];
            if (comp[k] >= 0)
            {
                comp[v] = comp[k];
                return comp[v];
            }
            else if (comp[k] == -2)
            {
            }
            else
            {
                look_up.push_back(k);
            }
        }
    }
    else
    {
        for (int i = 1; i <= n; i++) use[i] = true;
        for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
        for (int i = 1; i <= n; i++)
        {
            if (i == v || !use[i]) continue;

            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    /* for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            edge[i].push_back(j);
            edge[j].push_back(i);
        }
    } */
    for (int i = 1; i <= n; i++)
    {
        good[i] = false;
        comp[i] = -1;
        size[i] = edge[i].size();
        if (size[i] > n / 2)
        {
            good[i] = true;
            for (int j = 1; j <= n; j++)
            {
                use[j] = true;
            }
            for (int j = 0; j < size[i]; j++)
            {
                use[edge[i][j]] = false;
            }
            for (int j = 1; j <= n; j++)
            {
                if (use[j] == true && i != j)
                {
                    good_edge[i].push_back(j);
                }
            }
        }
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }
        comp[index] = nc++;
        for (int j = 1; j <= n; j++)
        {
            comp[j] = comp[index];
        }
        for (int j = 0; j < edge[index].size(); j++)
        {
            comp[edge[index][j]] = -1;
        }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 0; j < size[index]; j++)
        {
            if (comp[edge[index][j]] == -2) comp[edge[index][j]] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return edge[i].size() > edge[j].size();
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        order.push_back(j);
        comp[j] = comp[index];
    }
    sort(order.begin(), order.end(), cmp);
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 0; i < n; i++)
    {
        if (comp[order[i]] != -1) continue;
        search(order[i]);
        if (comp[order[i]] == -2)
        {
            comp[order[i]] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[order[i]];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];

int comp[500005];

int nc = 0;

void search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] > 0)
            {
                comp[v] = comp[i];
                return;
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        if (edge[v][j] == i)
        {
            j++;
            continue;
        }
        if (edge[v][j] < i)
        {
            j++;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        search(look_up[i]);
    }
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 0; i < n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if(comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
bool good[500005];
vector <int> good_edge[500005];

vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    if (good[v])
    {
        for (int i = 0; i < good_edge[v].size(); i++)
        {
            int k = good_edge[v][i];
            if (comp[k] >= 0)
            {
                comp[v] = comp[k];
                return comp[v];
            }
            else if (comp[k] == -2)
            {
            }
            else
            {
                look_up.push_back(k);
            }
        }
    }
    else
    {
        for (int i = 1; i <= n; i++) use[i] = true;
        for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
        for (int i = 1; i <= n; i++)
        {
            if (i == v || !use[i]) continue;

            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    // int start = clock();
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    /* for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            if (rand() % 200 == 0) continue;
            edge[i].push_back(j);
            edge[j].push_back(i);
        }
    }*/
    for (int i = 1; i <= n; i++)
    {
        good[i] = false;
        comp[i] = -1;
        size[i] = edge[i].size();
        if (size[i] > 2 * n / 3)
        {
            good[i] = true;
            for (int j = 1; j <= n; j++)
            {
                use[j] = true;
            }
            for (int j = 0; j < size[i]; j++)
            {
                use[edge[i][j]] = false;
            }
            for (int j = 1; j <= n; j++)
            {
                if (use[j] == true && i != j)
                {
                    good_edge[i].push_back(j);
                }
            }
        }
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }
        comp[index] = nc++;
        for (int j = 1; j <= n; j++)
        {
            comp[j] = comp[index];
        }
        for (int j = 0; j < edge[index].size(); j++)
        {
            comp[edge[index][j]] = -1;
        }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 0; j < size[index]; j++)
        {
            if (comp[edge[index][j]] == -2) comp[edge[index][j]] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    // printf("%d\n", clock() - start);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool is_edge(int i, int j)
{
    if (i == j) return false;
    int s = size[i];
    int low = 0;
    int high = s-1;
    while (low <= high)
    {
        int mid = (low + high) / 2 ;
        int k = edge[i][mid];
        if (j == k) return false;
        if (j > k) low = mid + 1;
        if (j < k) high = mid - 1;
    }
    return true;
}

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        order.push_back(i);
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
        size[i] = edge[i].size();
    }
    sort(order.begin(), order.end(), cmp);

    int index = order[0];
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 0; i < n; i++)
    {
        if (comp[order[i]] != -1) continue;
        search(order[i]);
        if (comp[order[i]] == -2)
        {
            comp[order[i]] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[order[i]];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
bool good[500005];
vector <int> good_edge[500005];

vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    if (good[v])
    {
        for (int i = 0; i < good_edge[v].size(); i++)
        {
            int k = good_edge[v][i];
            if (comp[k] >= 0)
            {
                comp[v] = comp[k];
                return comp[v];
            }
            else if (comp[k] == -2)
            {
            }
            else
            {
                look_up.push_back(k);
            }
        }
    }
    else
    {
        for (int i = 1; i <= n; i++) use[i] = true;
        for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
        for (int i = 1; i <= n; i++)
        {
            if (i == v || !use[i]) continue;

            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
            return comp[v];
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    /* for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            edge[i].push_back(j);
            edge[j].push_back(i);
        }
    } */
    for (int i = 1; i <= n; i++)
    {
        good[i] = false;
        comp[i] = -1;
        size[i] = edge[i].size();
        if (size[i] > n / 2)
        {
            good[i] = true;
            for (int j = 1; j <= n; j++)
            {
                use[j] = true;
            }
            for (int j = 0; j < size[i]; j++)
            {
                use[edge[i][j]] = false;
            }
            for (int j = 1; j <= n; j++)
            {
                if (use[j] == true && i != j)
                {
                    good_edge[i].push_back(j);
                }
            }
        }
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }
        comp[index] = nc++;
        for (int j = 1; j <= n; j++)
        {
            comp[j] = comp[index];
        }
        for (int j = 0; j < edge[index].size(); j++)
        {
            comp[edge[index][j]] = -1;
        }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 0; j < size[index]; j++)
        {
            if (comp[edge[index][j]] == -2) comp[edge[index][j]] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] > 0)
            {
                comp[v] = comp[i];
                return comp[i];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a > 0)
        {
            comp[v] = a;
            return a;
        }
    }
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] > 0)
            {
                comp[v] = comp[i];
                return comp[i];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a > 0)
        {
            comp[v] = a;
            return a;
        }
    }
    return comp[v];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return edge[i].size() < edge[j].size();
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        order.push_back(i);
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    sort(order.begin(), order.end(), cmp);
    int index = 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 0; i < n; i++)
    {
        if (comp[order[i]] != -1) continue;
        search(order[i]);
        if (comp[order[i]] == -2)
        {
            comp[order[i]] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[order[i]];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
bool good[500005];
vector <int> good_edge[500005];

vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    if (good[v])
    {
        for (int i = 0; i < good_edge[v].size(); i++)
        {
            int k = good_edge[v][i];
            if (comp[k] >= 0)
            {
                comp[v] = comp[k];
                return comp[v];
            }
            else if (comp[k] == -2)
            {
            }
            else
            {
                look_up.push_back(k);
            }
        }
    }
    else
    {
        for (int i = 1; i <= n; i++) use[i] = true;
        for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
        for (int i = 1; i <= n; i++)
        {
            if (i == v || !use[i]) continue;

            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    // int start = clock();
    /* for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }*/
    /* for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            if (rand() % 200 == 0) continue;
            edge[i].push_back(j);
            edge[j].push_back(i);
        }
    }*/
    for (int i = 1; i <= n; i++)
    {
        good[i] = false;
        comp[i] = -1;
        size[i] = edge[i].size();
        if (size[i] > 2 * n / 3)
        {
            good[i] = true;
            for (int j = 1; j <= n; j++)
            {
                use[j] = true;
            }
            for (int j = 0; j < size[i]; j++)
            {
                use[edge[i][j]] = false;
            }
            for (int j = 1; j <= n; j++)
            {
                if (use[j] == true && i != j)
                {
                    good_edge[i].push_back(j);
                }
            }
        }
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }
        comp[index] = nc++;
        for (int j = 1; j <= n; j++)
        {
            comp[j] = comp[index];
        }
        for (int j = 0; j < edge[index].size(); j++)
        {
            comp[edge[index][j]] = -1;
        }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 0; j < size[index]; j++)
        {
            if (comp[edge[index][j]] == -2) comp[edge[index][j]] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    // printf("%d\n", clock() - start);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
bool good[500005];
vector <int> good_edge[500005];

vector <int> order;
int size[500005];

int comp[500005];

int nc = 0;

bool use[500005];

int search(int v)
{
    comp[v] = -2;
    vector <int> look_up;
    int s = size[v];
    if (good[v])
    {
        for (int i = 0; i < good_edge[v].size(); i++)
        {
            int k = good_edge[v][i];
            if (comp[k] >= 0)
            {
                comp[v] = comp[k];
                return comp[v];
            }
            else if (comp[k] == -2)
            {
            }
            else
            {
                look_up.push_back(k);
            }
        }
    }
    else
    {
        for (int i = 1; i <= n; i++) use[i] = true;
        for (int j = 0; j < size[v]; j++) use[edge[v][j]] = false;
        for (int i = 1; i <= n; i++)
        {
            if (i == v || !use[i]) continue;

            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return size[i] < size[j];
}

int main()
{
    scanf("%d %d", &n, &m);
    // int start = clock();
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    /* for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
        {
            if (rand() % 200 == 0) continue;
            edge[i].push_back(j);
            edge[j].push_back(i);
        }
    }*/
    for (int i = 1; i <= n; i++)
    {
        good[i] = false;
        comp[i] = -1;
        size[i] = edge[i].size();
        if (size[i] > n / 3)
        {
            good[i] = true;
            for (int j = 1; j <= n; j++)
            {
                use[j] = true;
            }
            for (int j = 0; j < size[i]; j++)
            {
                use[edge[i][j]] = false;
            }
            for (int j = 1; j <= n; j++)
            {
                if (use[j] == true && i != j)
                {
                    good_edge[i].push_back(j);
                }
            }
        }
    }
    int index;
    int index_s = n + 1;
    for (int i = 1; i <= n; i++)
    {
        if(size[i] < index_s)
        {
            index_s = size[i];
            index = i;
        }
    }
        comp[index] = nc++;
        for (int j = 1; j <= n; j++)
        {
            comp[j] = comp[index];
        }
        for (int j = 0; j < edge[index].size(); j++)
        {
            comp[edge[index][j]] = -1;
        }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 0; j < size[index]; j++)
        {
            if (comp[edge[index][j]] == -2) comp[edge[index][j]] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    // printf("%d\n", clock() - start);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return edge[i].size() < edge[j].size();
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        order.push_back(i);
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    sort(order.begin(), order.end(), cmp);
    int index = 0;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 0; i < n; i++)
    {
        if (comp[order[i]] != -1) continue;
        search(order[i]);
        if (comp[order[i]] == -2)
        {
            comp[order[i]] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[order[i]];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];
vector <int> order;

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[v];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a >= 0)
        {
            comp[v] = a;
        }
    }
    return comp[v];
}

bool cmp(int i, int j)
{
    return edge[i].size() < edge[j].size();
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        order.push_back(j);
        comp[j] = comp[index];
    }
    sort(order.begin(), order.end(), cmp);
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 0; i < n; i++)
    {
        if (comp[order[i]] != -1) continue;
        search(order[i]);
        if (comp[order[i]] == -2)
        {
            comp[order[i]] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[order[i]];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    fflush(stdin);
    getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];

int comp[500005];

int nc = 0;

int search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] >= 0)
            {
                comp[v] = comp[i];
                return comp[i];
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        int a = search(look_up[i]);
        if (a > 0)
        {
            comp[v] = a;
            return a;
        }
    }
    return comp[v];
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

using namespace std;

int n, m;

vector <int> edge[500005];

int comp[500005];

int nc = 0;

void search(int v)
{
    comp[v] = -2;
    int j = 0;
    vector <int> look_up;
    int s = edge[v].size();
    for (int i = 1; i <= n; i++)
    {
        if (i == v) continue;

        if (j == s || edge[v][j] > i)
        {
            if (comp[i] > 0)
            {
                comp[v] = comp[i];
                return;
            }
            else if (comp[i] == -2)
            {
            }
            else
            {
                look_up.push_back(i);
            }
        }
        else if (edge[v][j] == i)
        {
            j++;
        }
        else if (edge[v][j] < i)
        {
            j++;
            i--;
        }
    }
    for (int i = 0; i < look_up.size(); i++)
    {
        search(look_up[i]);
    }
}

int main()
{
    scanf("%d %d", &n, &m);
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        edge[a].push_back(b);
        edge[b].push_back(a);
    }
    for (int i = 1; i <= n; i++)
    {
        comp[i] = -1;
        sort(edge[i].begin(), edge[i].end());
    }
    int index = (rand()) % n + 1;
    if (edge[index].size() > n / 2) index = (rand()) % n + 1;
    comp[index] = nc++;
    for (int j = 1; j <= n; j++)
    {
        comp[j] = comp[index];
    }
    for (int j = 0; j < edge[index].size(); j++)
    {
        comp[edge[index][j]] = -1;
    }
    for (int i = 1; i <= n; i++)
    {
        if (comp[i] != -1) continue;
        search(i);
        if (comp[i] == -2)
        {
            comp[i] = nc++;
        }
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == -2) comp[j] = comp[i];
        }
    }
    printf("%d\n", nc);
    for (int i = 0; i < nc; i++)
    {
        int num = 0;
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) num++;
        }
        printf("%d ", num);
        for (int j = 1; j <= n; j++)
        {
            if (comp[j] == i) printf("%d ", j);
        }
        printf("\n");
    }
    //fflush(stdin);
    //getchar();
}


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

const int N=500010;
const int inf=0x3f3f3f3f;

using namespace std;

int n,m;
int vis[N];
set<int> st;
vector<int> vt[N],ret[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	int tot=0;
	for(int i=1;i<=n;i++)
		st.insert(i);
	while(st.begin()!=st.end())
	{
		tot++;
		int u=*st.begin();
		queue<int> que;
		que.push(u);ret[tot].push_back(u);
		st.erase(u);
		while(!que.empty())
		{
			int v=que.front();
			que.pop();
			int sz=vt[v].size();
			for(int i=0;i<sz;i++)
				vis[vt[v][i]]=v;
			for(set<int>::iterator it=st.begin();it!=st.end();it++)
			{
				if(vis[*it]!=v)
				{
					ret[tot].push_back(*it);
					que.push(*it);
					st.erase(*it);
				}
			}
		}
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
	{
		sort(ret[i].begin(),ret[i].end());
		int sz=ret[i].size();
		printf("%d",sz);
		for(int j=0;j<sz;j++)
			printf(" %d",ret[i][j]);
		puts("");
	}
	return 0;
}


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

const int N=500010;
const int inf=0x3f3f3f3f;

using namespace std;

int n,m;
int vis[N];
bool q[N];
set<int> st;
vector<int> vt[N],ret[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	int tot=0;
	for(int i=1;i<=n;i++)
		st.insert(i);
	while(st.begin()!=st.end())
	{
		tot++;
		int u=*st.begin();
		queue<int> que;
		que.push(u);
		while(!que.empty())
		{
			int v=que.front();
			que.pop();
			if(st.count(v))
			{
				ret[tot].push_back(v);
				st.erase(v);
			}
			int sz=vt[v].size();
			for(int i=0;i<sz;i++)
				vis[vt[v][i]]=v;
			for(set<int>::iterator it=st.begin();it!=st.end();it++)
			{
				if(vis[*it]!=v && (!q[*it]))
					que.push(*it),q[*it]=1;
			}
		}
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
	{
		sort(ret[i].begin(),ret[i].end());
		int sz=ret[i].size();
		printf("%d",sz);
		for(int j=0;j<sz;j++)
			printf(" %d",ret[i][j]);
		puts("");
	}
	return 0;
}


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

const int N=500010;
const int inf=0x3f3f3f3f;

using namespace std;

int n,m;
int vis[N];
set<int> st;
vector<int> vt[N],ret[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	int tot=0;
	for(int i=1;i<=n;i++)
		st.insert(i);
	while(st.begin()!=st.end())
	{
		tot++;
		int u=*st.begin();
		queue<int> que;
		que.push(u);ret[tot].push_back(u);
		st.erase(u);
		while(!que.empty())
		{
			int v=que.front();
			que.pop();
			int sz=vt[v].size();
			for(int i=0;i<sz;i++)
				vis[vt[v][i]]=v;
			for(set<int>::iterator it=st.begin();it!=st.end();it++)
			{
				if(vis[*it]!=v)
				{
					ret[tot].push_back(*it);
					st.erase(*it);
					que.push(*it);
				}
			}
		}
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
	{
		sort(ret[i].begin(),ret[i].end());
		int sz=ret[i].size();
		printf("%d",sz);
		for(int j=0;j<sz;j++)
			printf(" %d",ret[i][j]);
		puts("");
	}
	return 0;
}


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

const int N=500010;
const int inf=0x3f3f3f3f;

using namespace std;

int n,m;
int vis[N];
bool q[N];
set<int> st;
int l[N];
vector<int> vt[N],ret[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	int tot=0;
	for(int i=1;i<=n;i++)
		l[i-1]=i;
	l[n]=-1;
	while(l[0]+1)
	{
		tot++;
		int u=l[0];
		queue<int> que;
		que.push(u);
		ret[tot].push_back(u);
		l[0]=l[u];
		while(!que.empty())
		{
			int v=que.front();
			que.pop();
			int sz=vt[v].size();
			for(int i=0;i<sz;i++)
				vis[vt[v][i]]=v;
			for(int pre=0,i=l[0];i+1;pre=i,i=l[i])
			{
				if(vis[i]==v) continue;
				que.push(i);
				ret[tot].push_back(i);
				i=pre;l[i]=l[l[i]];
			}
		}
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
	{
		sort(ret[i].begin(),ret[i].end());
		int sz=ret[i].size();
		printf("%d",sz);
		for(int j=0;j<sz;j++)
			printf(" %d",ret[i][j]);
		puts("");
	}
	return 0;
}


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

const int N=500010;
const int inf=0x3f3f3f3f;

using namespace std;

int n,m;
int vis[N];
set<int> st;
vector<int> vt[N],ret[N];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	int tot=0;
	for(int i=1;i<=n;i++)
		st.insert(i);
	while(st.begin()!=st.end())
	{
		tot++;
		int u=*st.begin();
		queue<int> que;
		que.push(u);
		while(!que.empty())
		{
			int v=que.front();
			que.pop();
			if(st.count(v))
			{
				ret[tot].push_back(v);
				st.erase(v);
			}
			int sz=vt[v].size();
			for(int i=0;i<sz;i++)
				vis[vt[v][i]]=v;
			for(set<int>::iterator it=st.begin();it!=st.end();it++)
			{
				if(vis[*it]!=v)
					que.push(*it);
			}
		}
	}
	printf("%d\n",tot);
	for(int i=1;i<=tot;i++)
	{
		sort(ret[i].begin(),ret[i].end());
		int sz=ret[i].size();
		printf("%d",sz);
		for(int j=0;j<sz;j++)
			printf(" %d",ret[i][j]);
		puts("");
	}
	return 0;
}


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

inline void read(register int *k) {
	register char c; *k=0;
	do { c=getchar(); } while(c<'0' || c>'9');
	do { *k=*k*10+c-'0'; c=getchar(); } while(c>='0' && c<='9');
}

int main() {
	read(&n);
	read(&m);
	FOR(i,0,m) {
		int x,y;
		read(&x);
		read(&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));
}

inline void read(register int *k) {
	register char c; *k=0;
	do { c=getchar(); } while(c<'0' || c>'9');
	do { *k=*k*10+c-'0'; c=getchar(); } while(c>='0' && c<='9');
}

int main() {
	read(&n);
	read(&m);
	FOR(i,0,n) {
		adj[i].reserve(10);
		vert[i].reserve(10);
	}
	FOR(i,0,m) {
		int x,y;
		read(&x);
		read(&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;
	}
}