#include<cstdio> #include<algorithm> #include<cstring> using namespace std; struct my{ int next; int v; }; const int maxn=10000; int low[maxn],dfsn[maxn],adj[maxn],fa,sfa,dfn; int bs[maxn],cnt; bool bridge[maxn*2]; int sadj[maxn]; my sbian[maxn*2]; my bian[maxn*2]; 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,int dage){ dfsn[x]=low[x]=++dfn; for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(!dfsn[v]){ tarjan(v,i); low[x]=min(low[x],low[v]); if(dfsn[x]<low[v]){ bridge[i]=bridge[i^1]=1; } } else if(i!=(dage^1)){ low[x]=min(low[x],dfsn[v]); } } } void dfs(int x){ bs[x]=cnt; for (int i=adj[x];i;i=bian[i].next){ int v=bian[i].v; if(bs[v]||bridge[i]) continue; dfs(v); } } int main(){ int n,m; int u,v; fa=1; sfa=1; 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]) tarjan(i,0); for (int i=1;i<=n;i++){ if(!bs[i]){ cnt++; dfs(i); } } //for (int i=2;i<fa;i+=2) if(bridge[i]) printf("%d %d\n",bian[i].v,bian[i^1].v); for (int i=2;i<=fa;i++){ int x=bian[i].v,y=bian[i^1].v; if(bs[x]==bs[y]) continue; smyinsert(bs[x],bs[y]);//不需连两条边,算法自己会连成双向边 } for (int i=1;i<=cnt;i++){ printf("%d ",i); for (int j=sadj[i];j;j=sbian[j].next){ printf("%d ",sbian[j].v); } printf("\n"); } return 0; }