#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<stack>
using namespace std;
struct my{
int next;
int v;
};
const int maxn=10000;
int adj[maxn],low[maxn],dfsn[maxn],dfn,fa,id[maxn],sadj[maxn],sfa;
my bian[maxn*2],sbian[maxn*2];
bool cut[maxn];
int sccnum;
int s[maxn],top,root;
vector<int>scc[maxn];
void myinsert(int u,int v){
bian[++fa].v=v;
bian[fa].next=adj[u];
adj[u]=fa;
}
void smyinsert(int u,int v){
sbian[++sfa].v=v;
sbian[sfa].next=sadj[u];
sadj[u]=sfa;
}
void tarjan(int x){
s[++top]=x;
low[x]=dfsn[x]=++dfn;
int ch=0;
if(x==root&&!adj[x]){
scc[++sccnum].push_back(x);
return ;
}
for (int i=adj[x];i;i=bian[i].next){
int v=bian[i].v;
if(!dfsn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
if(dfsn[x]<=low[v]){
ch++;
sccnum++;
int z;
do{
z=s[top--];
scc[sccnum].push_back(z);
}while(z!=v);
scc[sccnum].push_back(x);
if(x!=root||ch>1) cut[x]=true;
}
}else low[x]=min(low[x],dfsn[v]);
}
}
int main(){
int n,m;
int u,v;
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
myinsert(u,v);
myinsert(v,u);
}
for (int i=1;i<=n;i++){
if(!dfsn[i]) {
root=i;
tarjan(i);
}
}
int num=sccnum;
for (int i=1;i<=n;i++) if(cut[i]) id[i]=++num;
for (int i=1;i<=sccnum;i++){
for (int j=0;j<scc[i].size();j++){
int x=scc[i][j];
if(cut[x]){
smyinsert(i,id[x]);
smyinsert(id[x],i);
}
}
}
for (int i=1;i<=num;i++){
printf("%d ",i);
for (int j=sadj[i];j;j=sbian[j].next){
int v=sbian[j].v;
printf("%d ",v);
}
printf("\n");
}
return 0;
}