P1008

#include <bits/stdc++.h>

const int N = 500010, M = 2000010;
int n, m;
int head[N], nxt[M << 1], to[M << 1], idx;
int dfn[N], low[N], tsp;
int stk[N], top, root;
int vdcc;
std::vector<int> pts[N];

void add(int u, int v) {
    nxt[idx] = head[u];
    to[idx] = v;
    head[u] = idx;
    ++ idx;
    return;
}
void dfsearch(int u, int last_ed) {
    ++ tsp;
    dfn[u] = low[u] = tsp;
    ++ top;
    stk[top] = u;

    if (u == root && head[u] == -1) {
        ++ vdcc;
        pts[vdcc].push_back(u);
        return;
    }
    for (int i = head[u]; i != -1; i = nxt[i]) {
        int e = to[i];
        if (!dfn[e]) {
            dfsearch(e, i);
            low[u] = std::min(low[u], low[e]);
            if (dfn[u] <= low[e]) {
                int topele;
                ++ vdcc;
                do {
                    topele = stk[top];
                    -- top;
                    pts[vdcc].push_back(topele);
                } while (topele != e);
                pts[vdcc].push_back(u);
            }
        } else if ((i xor 1) != last_ed) {
            low[u] = std::min(low[u], dfn[e]);
        }
    }

    return;
}


int main(void) {
    memset(head, -1, sizeof(head));
    idx = 0;

    int inpu, inpv;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; ++ i) {
        scanf("%d%d", &inpu, &inpv);
        if (inpu == inpv) {
            continue;
        }
        add(inpu, inpv);
        add(inpv, inpu);
    }
    tsp = 0, top = 0, vdcc = 0;
    for (int i = 1; i <= n; ++ i) {
        if (!dfn[i]) {
            root = i;
            dfsearch(i, -1);
        }
    }
    printf("%d\n", vdcc);
    for (int i = 1; i <= vdcc; ++ i, puts("")) {
        int len = pts[i].size();
        printf("%d ", len);
        for (int j = 0; j < len; ++ j) {
            printf("%d ", pts[i][j]);
        }
    }

    return 0;
}