#include <bits/stdc++.h>
using namespace std;
const int MAX1 = 100002, MAX2 = 200002;
vector<int> vs[MAX1], es[MAX2];
int vsn, esn;
bool isolate[MAX1], vist[MAX1];
int iss[MAX1];
int cnt, ent, cnn, sn, t1, nxt;
int ct[MAX1], et[MAX1], tt[MAX1 * 4], tn;
int n, m;
struct edge {
  int to, nxt, eidx;
  bool mask;
  edge() {}
};
edge edges[MAX2 << 1];
int ees;
int head[MAX1], d[MAX1];
inline void add(int a, int b, int eidx) {
  edges[ees].nxt = head[a], edges[ees].to = b, edges[ees].eidx = eidx,
  head[a] = ees++;
  edges[ees].nxt = head[b], edges[ees].to = a, edges[ees].eidx = eidx,
  head[b] = ees++;
}
vector<int> Q;
pair<int, int> ee[MAX2];
int een;
int reE, reV;
void dfs(int v) {
  vist[v] = 1;
  cnt++;
  for (int i = head[v]; ~i; i = edges[i].nxt) {
    int u = edges[i].to;
    if (vist[u] == 0 && edges[i].mask == 0) {
      edges[i].mask = edges[i ^ 1].mask = 1;
      ent++;
      dfs(u);
    } else if (edges[i].mask == 0) {
      edges[i].mask = edges[i ^ 1].mask = 1;
      reE = edges[i].eidx, reV = v, ent++;
    }
  }
}
void dfs2(int v) {
  vist[v] = 1, tt[tn++] = v;
  int x;
  for (int i = head[v]; ~i; i = edges[i].nxt) {
    int u = edges[i].to;
    if (vist[u] == 0 && edges[i].mask == 0) {
      edges[i].mask = edges[i ^ 1].mask = 1;
      dfs2(u);
      tt[tn++] = v;
      ent--;
      if (ent == 0 && nxt != -1) {
        es[esn].push_back(edges[i].eidx);
        es[esn].push_back(v), es[esn++].push_back(nxt);
        for (int j = 0; j < tn; j++) vs[vsn].push_back(tt[j]);
        vsn++, tn = 0;
      } else if (t1 != sn) {
        x = iss[t1++];
        for (int j = 0; j < tn; j++) vs[vsn].push_back(tt[j]);
        vsn++, tn = 0;
        es[esn].push_back(edges[i].eidx);
        es[esn].push_back(v), es[esn++].push_back(x);
        tt[tn++] = x, tt[tn++] = v;
      }
    } else if (edges[i].mask == 0) {
      edges[i].mask = edges[i ^ 1].mask = 1;
      ent--;
      if (t1 != sn) {
        x = iss[t1++];
        for (int j = 0; j < tn; j++) vs[vsn].push_back(tt[j]);
        vsn++, tn = 0;
        es[esn].push_back(edges[i].eidx);
        es[esn].push_back(v), es[esn++].push_back(x);
        tt[tn++] = x, tt[tn++] = v;
      }
    }
  }
}
void print() {
  for (int v = 1; v <= n; v++) {
    printf("v = %d : ", v);
    for (int j = head[v]; ~j; j = edges[j].nxt) printf("%d->", edges[j].to);
    printf("\n");
  }
}
inline void ini() {
  for (int i = 0; i < ees; i++) edges[i].mask = 0;
}
int main() {
  scanf("%d%d", &n, &m);
  een = 1;
  memset(head, -1, sizeof(head)), ees = 0;
  for (int i = 1; i <= m; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    ee[een++] = {a, b};
    add(a, b, i);
    ++d[a], ++d[b];
  }
  een--;
  memset(vist, 0, sizeof(vist));
  reV = -1;
  ini();
  for (int i = 1; i <= n; i++) {
    if (vist[i] == 0) {
      cnt = ent = 0;
      dfs(i);
      if (cnt == 1) {
        isolate[i] = 1, iss[sn++] = i;
      } else
        ct[i] = cnt, et[i] = ent, cnn++;
    }
  }
  if (isolate[1] == 0) {
    if (cnn - 1 + sn <= m) {
      for (int i = 1; i <= n; i++) {
        if (!isolate[i] && ct[i]) Q.push_back(i);
      }
      for (int i = 0; i < Q.size(); i++) {
        if (Q[i] == 1) {
          swap(Q[i], Q[0]);
          break;
        }
      }
      memset(vist, 0, sizeof(vist));
      t1 = 0;
      ini();
      for (int i = 0; i < Q.size(); i++) {
        if (i != (int)Q.size() - 1)
          nxt = Q[i + 1];
        else
          nxt = -1;
        ent = et[Q[i]];
        dfs2(Q[i]);
      }
      printf("YES\n");
      printf("%d\n", esn);
      for (int i = 0; i < esn; i++) {
        printf("%d ", vs[i].size());
        for (int j = 0; j < vs[i].size(); j++) printf("%d ", vs[i][j]);
        printf("\n");
        for (int j = 0; j < es[i].size(); j++) printf("%d ", es[i][j]);
        printf("\n");
      }
      printf("%d ", tn);
      for (int i = 0; i < tn; i++) printf("%d ", tt[i]);
      printf("\n");
    } else
      printf("NO\n");
  } else if (cnn != 0) {
    int v, t2;
    if (reV != -1 && cnn - 1 + sn <= m) {
      v = reV, t2 = reE;
    } else if (reV == -1 && cnn - 1 + sn <= m - 1) {
      for (int i = 2; i <= n; i++)
        if (d[i] >= 2) {
          v = i;
          break;
        }
      t2 = edges[head[v]].eidx;
    } else {
      printf("NO\n");
      return 0;
    }
    memset(head, -1, sizeof(head)), ees = 0;
    for (int i = 1; i <= een; i++) {
      if (i != t2) {
        add(ee[i].first, ee[i].second, i);
      }
    }
    memset(vist, 0, sizeof(vist)), memset(isolate, 0, sizeof(isolate)),
        memset(ct, 0, sizeof(ct)), memset(et, 0, sizeof(et)), sn = 0, cnn = 0;
    for (int i = 1; i <= n; i++) d[i] = i;
    swap(d[1], d[v]);
    ini();
    for (int i = 1; i <= n; i++) {
      int u = d[i];
      if (vist[u] == 0) {
        cnt = ent = 0;
        dfs(u);
        if (cnt == 1) {
          isolate[u] = 1;
          if (u != 1) iss[sn++] = i;
        } else
          ct[u] = cnt, et[u] = ent, cnn++;
      }
    }
    vs[vsn++].push_back(1);
    es[esn].push_back(t2), es[esn].push_back(1), es[esn++].push_back(v);
    for (int i = 1; i <= n; i++) {
      if (!isolate[i] && ct[i]) Q.push_back(i);
    }
    for (int i = 0; i < Q.size(); i++) {
      if (Q[i] == v) {
        swap(Q[i], Q[0]);
        break;
      }
    }
    memset(vist, 0, sizeof(vist));
    t1 = 0;
    ini();
    for (int i = 0; i < Q.size(); i++) {
      if (i != (int)Q.size() - 1)
        nxt = Q[i + 1];
      else
        nxt = -1;
      ent = et[Q[i]];
      dfs2(Q[i]);
    }
    printf("YES\n");
    printf("%d\n", esn);
    for (int i = 0; i < esn; i++) {
      printf("%d ", vs[i].size());
      for (int j = 0; j < vs[i].size(); j++) printf("%d ", vs[i][j]);
      printf("\n");
      for (int j = 0; j < es[i].size(); j++) printf("%d ", es[i][j]);
      printf("\n");
    }
    printf("%d ", tn);
    for (int i = 0; i < tn; i++) printf("%d ", tt[i]);
    printf("\n");
  } else {
    if (n != 1)
      printf("NO\n");
    else
      printf("YES\n0\n1 1\n");
  }
  return 0;
}
