#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
ifstream in("biconex.in");
ofstream out("biconex.out");
struct mch
{
int x,y;
};
vector<int> vecini[MAXN];
int n;
vector<int> componente_conexe[MAXN];
int nr_componente_conexe = 0;
mch stiva[MAXN];
int l_stiva;
int id[MAXN],jos[MAXN];
void citire()
{
int m;
in >> n >> m;
for (int i = 1;i <= m;++i)
{
int x,y;
in >> x >> y;
vecini[x].push_back(y);
vecini[y].push_back(x);
}
}
void adaugare_componenta_conexa(int x, int y)
{
++nr_componente_conexe;
int tx,ty;
do
{
tx = stiva[l_stiva].x;
ty = stiva[l_stiva].y;
--l_stiva;
componente_conexe[nr_componente_conexe].push_back(tx);
componente_conexe[nr_componente_conexe].push_back(ty);
}while(tx != x || ty != y);
sort(componente_conexe[nr_componente_conexe].begin(),
componente_conexe[nr_componente_conexe].end());
componente_conexe[nr_componente_conexe].erase(
unique(componente_conexe[nr_componente_conexe].begin(),
componente_conexe[nr_componente_conexe].end()),
componente_conexe[nr_componente_conexe].end());
}
void dfs(int nod, int tata, int numar)
{
id[nod] = numar;
jos[nod] = numar;
for (unsigned int i = 0;i < vecini[nod].size();++i)
{
int vecin = vecini[nod][i];
if (vecin == tata)
continue;
if (id[vecin] == -1)
{
stiva[++l_stiva] = (mch){nod, vecin};
dfs(vecin, nod, numar + 1);
if (jos[vecin] < jos[nod])
jos[nod] = jos[vecin];
if (jos[vecin] >= id[nod])
adaugare_componenta_conexa(nod, vecin);
}
else if (id[vecin] < jos[nod])
jos[nod] = id[vecin];
}
}
void afisare()
{
out << nr_componente_conexe << '\n';
for (int i = 1;i <= nr_componente_conexe;++i)
{
for (unsigned int j = 0;j < componente_conexe[i].size();++j)
out << componente_conexe[i][j] << ' ';
out << '\n';
}
}
int main()
{
citire();
for (int i = 0;i <= n + 1;++i)
id[i] = -1;
dfs(1,0,0);
afisare();
return 0;
}