- import java.io.File;
- import java.io.PrintWriter;
- import java.util.*;
- public class Main {
- static class edge {
- int a;
- int b;
- edge(int a, int b) {
- this.a = a;
- this.b = b;
- }
- }
- static class way {
- int i;
- LinkedList<Integer> w = new LinkedList<Integer>();
- way(int i) {
- this.i = i;
- }
- }
- static class DisjointSets {
- static Random rnd = new Random();
- int[] p;
- int size;
- void init() {
- for (int i = 0; i < p.length; i++) {
- p[i] = i;
- }
- }
- DisjointSets(int size) {
- p = new int[size];
- this.size = size;
- init();
- }
- void copy(DisjointSets A)
- {
- for (int i = 0; i < size; ++i)
- p[i] = A.p[i];
- }
- int root(int x) {
- if (p[x] != x) {
- p[x] = root(p[x]);
- }
- return p[x];
- }
- void unite(int a, int b) {
- a = root(a);
- b = root(b);
- if (rnd.nextBoolean()) {
- p[a] = b;
- } else {
- p[b] = a;
- }
- }
- }
- static boolean checkA(int a, int b, DisjointSets ds) {
- if (ds.root(a) == ds.root(b))
- return false;
- return true;
- }
- public static void main(String args[]) {
- try {
- Scanner in = new Scanner(new File("multispan.in"));
- PrintWriter out = new PrintWriter(new File("multispan.out"));
- int m, n;
- n = in.nextInt();
- m = in.nextInt();
- int a, b;
- int[] I = new int[m+1];
- edge[] edges = new edge[m];
- for (int i = 0; i < m; ++i) {
- a = in.nextInt() - 1;
- b = in.nextInt() - 1;
- edges[i] = new edge(a, b);
- }
- int k = 1;
- int size = 0;
- while (true) {
- if (k*(n-1) == size){
- k++;
- }
- LinkedList<Integer> []Ij = new LinkedList[k+1];
- int []A = new int[m];
- for (int i = 0; i <= k; ++i){
- Ij[i] = new LinkedList<Integer>();
- }
- for (int i = 0; i < m; ++i)
- {
- Ij[I[i]].add(i);
- }
- for (int j = 1; j<=k; ++j){
- DisjointSets ds = new DisjointSets(n);
- for (Integer i : Ij[j]){
- ds.unite(edges[i].a, edges[i].b);
- }
- for (int i = 0; i < m; ++i){
- if (checkA(edges[i].a, edges[i].b, ds)){
- A[i] = j;
- }
- }
- }
- boolean add = false;
- for (int i = 0; i < m; ++i){
- if ((A[i] != 0) && (I[i] == 0)){
- I[i] = A[i];
- add = true;
- size++;
- break;
- }
- }
- if (add){
- continue;
- }
- Queue<way> bfs = new LinkedList<way>();
- boolean[] bfc = new boolean[m];
- for (int i = 0; i < m; ++i) {
- if (A[i] != 0) {
- way d = new way(i);
- d.w.add(i);
- bfs.add(d);
- bfc[i] = true;
- }
- }
- way p = new way(-1);
- boolean end = false;
- while (!bfs.isEmpty()) {
- p = bfs.poll();
- if (I[p.i] == 0){
- end = true;
- break;
- }
- DisjointSets ds = new DisjointSets(n);
- for (Integer j : Ij[I[p.i]]){
- if (j != p.i){
- ds.unite(edges[j].a, edges[j].b);
- }
- }
- for (int i =0; i < m; ++i){
- if (!bfc[i]){
- if (checkA(edges[i].a, edges[i].b, ds)){
- way d = new way(i);
- d.w = (LinkedList<Integer>) p.w.clone();
- d.w.add(i);
- bfs.add(d);
- bfc[i] = true;
- }
- }
- }
- }
- if (!end)
- break;
- int first = p.w.pollFirst();
- int newPos = I[first];
- I[first] = A[first];
- for (Integer i : p.w) {
- first = I[i];
- I[i] = newPos;
- newPos = first;
- }
- size++;
- }
- LinkedList<Integer> []Ij = new LinkedList[k+1];
- for (int i = 0; i <= k; ++i){
- Ij[i] = new LinkedList<Integer>();
- }
- for (int i = 0; i < m; ++i)
- {
- Ij[I[i]].add(i);
- }
- if (k*(n-1) != size){
- k--;
- }
- out.println(k);
- for (int j = 1; j <= k; j++){
- for (Integer i : Ij[j]) {
- out.print((i + 1) + " ");
- }
- out.println();
- }
- out.close();
- } catch (Exception e) {
- System.out.print(e);
- }
- }
- }