Berland has managed to repel the flatlanders' attack and is now starting the counter attack.

Flatland has n cities, numbered from 1 to n, and some pairs of them are connected by bidirectional roads. The Flatlandian maps show roads between cities if and only if there is in fact no road between this pair of cities (we do not know whether is it a clever spy-proof strategy or just saving ink). In other words, if two cities are connected by a road on a flatland map, then there is in fact no road between them. The opposite situation is also true: if two cities are not connected by a road on a flatland map, then in fact, there is a road between them.

The berlanders got hold of a flatland map. Now Vasya the Corporal is commissioned by General Touristov to find all such groups of flatland cities, that in each group of cities you can get from any city to any other one, moving along the actual roads. Also the cities from different groups are unreachable from each other, moving along the actual roads. Indeed, destroying such groups one by one is much easier than surrounding all Flatland at once!

Help the corporal complete this task and finally become a sergeant! Don't forget that a flatland map shows a road between cities if and only if there is in fact no road between them. 

Input

The first line contains two space-separated integers n and m (1 ≤ n ≤ 5·105, 0 ≤ m ≤ 106) — the number of cities and the number of roads marked on the flatland map, correspondingly.

Next m lines contain descriptions of the cities on the map. The i-th line contains two integers ai and bi (1 ≤ ai, bi ≤ n, ai ≠ bi) — the numbers of cities that are connected by the i-th road on the flatland map.

It is guaranteed that each pair of cities occurs in the input no more than once.

Output

On the first line print number k — the number of groups of cities in Flatland, such that in each group you can get from any city to any other one by flatland roads. At the same time, the cities from different groups should be unreachable by flatland roads.

On each of the following k lines first print ti (1 ≤ ti ≤ n) — the number of vertexes in the i-th group. Then print space-separated numbers of cities in the i-th group.

The order of printing groups and the order of printing numbers in the groups does not matter. The total sum ti for all k groups must equal n.

Examples

Input

4 4
1 2
1 3
4 2
4 3


Output

2
2 1 4 
2 2 3 


Input

3 1
1 2


Output

1
3 1 2 3 

Note

In the first sample there are roads only between pairs of cities 1-4 and 2-3.

In the second sample there is no road between cities 1 and 2, but still you can get from one city to the other one through city number 3.
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.Random;
import java.util.NoSuchElementException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        CounterAttack solver = new CounterAttack();
        solver.solve(1, in, out);
        out.close();
    }

    static class CounterAttack {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            EzIntArrayList[] bad = new EzIntArrayList[n + 1];
            Arrays.setAll(bad, i -> new EzIntArrayList());
            for (int i = 0; i < m; i++) {
                int u = in.nextInt();
                int v = in.nextInt();
                bad[u].add(v);
                bad[v].add(u);
            }

            CounterAttack.DSU dsu = new CounterAttack.DSU(n);

            int minV = 1;
            int minD = Integer.MAX_VALUE / 2;
            for (int i = 1; i <= n; i++) {
                if (bad[i].size() < minD) {
                    minV = i;
                    minD = bad[i].size();
                }
            }

            bad[minV].sort();
            for (int i = 1; i <= n; i++) {
                if (!bad[minV].binarySearch(i)) {
                    dsu.unite(minV, i);
                }
            }

            // 2mlog(2m) + 2mlog(2m) + nlog(2m)
            for (EzIntIterator it = bad[minV].iterator(); it.hasNext(); ) {
                int v = it.next();
                bad[v].sort();
                for (int i = 1; i <= n; i++) {
                    if (!bad[v].binarySearch(i)) {
                        dsu.unite(v, i);
                    }
                }
            }

            EzIntArrayList[] comps = new EzIntArrayList[n + 1];
            Arrays.setAll(comps, i -> new EzIntArrayList());
            for (int i = 1; i <= n; i++) {
                int ri = dsu.find(i);
                comps[ri].add(i);
            }

            out.println(dsu.numSets);
            for (EzIntArrayList comp : comps) {
                if (!comp.isEmpty()) {
                    out.print(comp.size() + " ");
                    for (EzIntIterator it = comp.iterator(); it.hasNext(); ) {
                        int u = it.next();
                        out.print(u + " ");
                    }
                    out.println();
                }
            }
        }

        static class DSU {
            int[] link;
            int[] sz;
            int numSets;

            DSU(int n) {
                link = new int[n + 1];
                Arrays.setAll(link, i -> i);
                sz = new int[n + 1];
                Arrays.fill(sz, 1);
                numSets = n;
            }

            int find(int u) {
                while (u != link[u]) {
                    u = link[u];
                }
                return u;
            }

            void unite(int u, int v) {
                u = find(u);
                v = find(v);
                if (u != v) {
                    if (sz[u] > sz[v]) {
                        int tmp = u;
                        u = v;
                        v = tmp;
                    }
                    link[u] = v;
                    sz[v] += sz[u];
                    numSets--;
                }
            }

        }

    }

    static final class EzIntSort {
        private static final Random rnd = new Random();

        private EzIntSort() {
        }

        private static void randomShuffle(int[] a, int left, int right) {
            for (int i = left; i < right; i++) {
                int j = i + rnd.nextInt(right - i);
                int tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }

        public static void safeArraysSort(int[] a, int left, int right) {
            if (left > right || left < 0 || right > a.length) {
                throw new IllegalArgumentException(
                        "Incorrect range [" + left + ", " + right + ") was specified for sorting, length = " + a.length);
            }
            randomShuffle(a, left, right);
            Arrays.sort(a, left, right);
        }

    }

    static class InputReader {
        private final InputStream is;
        private final byte[] inbuf = new byte[1024];
        private int lenbuf = 0;
        private int ptrbuf = 0;

        public InputReader(InputStream stream) {
            is = stream;
        }

        private int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = num * 10 + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

    }

    static final class PrimitiveHashCalculator {
        private PrimitiveHashCalculator() {
        }

        public static int getHash(int x) {
            return x;
        }

    }

    static class EzIntArrayList implements EzIntList, EzIntStack {
        private static final int DEFAULT_CAPACITY = 10;
        private static final double ENLARGE_SCALE = 2.0;
        private static final int HASHCODE_INITIAL_VALUE = 0x811c9dc5;
        private static final int HASHCODE_MULTIPLIER = 0x01000193;
        private int[] array;
        private int size;

        public EzIntArrayList() {
            this(DEFAULT_CAPACITY);
        }

        public EzIntArrayList(int capacity) {
            if (capacity < 0) {
                throw new IllegalArgumentException("Capacity must be non-negative");
            }
            array = new int[capacity];
            size = 0;
        }

        public EzIntArrayList(EzIntCollection collection) {
            size = collection.size();
            array = new int[size];
            int i = 0;
            for (EzIntIterator iterator = collection.iterator(); iterator.hasNext(); ) {
                array[i++] = iterator.next();
            }
        }

        public EzIntArrayList(int[] srcArray) {
            size = srcArray.length;
            array = new int[size];
            System.arraycopy(srcArray, 0, array, 0, size);
        }

        public EzIntArrayList(Collection<Integer> javaCollection) {
            size = javaCollection.size();
            array = new int[size];
            int i = 0;
            for (int element : javaCollection) {
                array[i++] = element;
            }
        }

        public int size() {
            return size;
        }

        public boolean isEmpty() {
            return size == 0;
        }

        public EzIntIterator iterator() {
            return new EzIntArrayListIterator();
        }

        public boolean add(int element) {
            if (size == array.length) {
                enlarge();
            }
            array[size++] = element;
            return true;
        }

        private void enlarge() {
            int newSize = Math.max(size + 1, (int) (size * ENLARGE_SCALE));
            int[] newArray = new int[newSize];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }

        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            EzIntArrayList that = (EzIntArrayList) o;

            if (size != that.size) {
                return false;
            }
            for (int i = 0; i < size; i++) {
                if (array[i] != that.array[i]) {
                    return false;
                }
            }
            return true;
        }

        public int hashCode() {
            int hash = HASHCODE_INITIAL_VALUE;
            for (int i = 0; i < size; i++) {
                hash = (hash ^ PrimitiveHashCalculator.getHash(array[i])) * HASHCODE_MULTIPLIER;
            }
            return hash;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append('[');
            for (int i = 0; i < size; i++) {
                sb.append(array[i]);
                if (i < size - 1) {
                    sb.append(", ");
                }
            }
            sb.append(']');
            return sb.toString();
        }

        public void sort() {
            EzIntSort.safeArraysSort(array, 0, size);
        }

        public int lowerBound(int val) {
            int ret = -1;
            for (int jump = size; jump >= 1; jump /= 2) {
                while (ret + jump < size && array[ret + jump] < val) {
                    ret += jump;
                }
            }
            return ret + 1;
        }

        public boolean binarySearch(int val) {
            int lb = lowerBound(val);
            return lb < size && array[lb] == val;
        }

        private class EzIntArrayListIterator implements EzIntIterator {
            private int curIndex = 0;

            public boolean hasNext() {
                return curIndex < size;
            }

            public int next() {
                if (curIndex == size) {
                    throw new NoSuchElementException("Iterator doesn't have more elements");
                }
                return array[curIndex++];
            }

        }

    }

    static interface EzIntIterator {
        boolean hasNext();

        int next();

    }

    static interface EzIntList extends EzIntCollection {
        int size();

        EzIntIterator iterator();

        boolean equals(Object object);

        int hashCode();

        String toString();

    }

    static interface EzIntCollection {
        int size();

        EzIntIterator iterator();

        boolean equals(Object object);

        int hashCode();

        String toString();

    }

    static interface EzIntStack extends EzIntCollection {
        int size();

        EzIntIterator iterator();

        boolean equals(Object object);

        int hashCode();

        String toString();

    }
}

