#include <bits/stdc++.h>
using namespace std;
bool debug;
const int inf = 1e9 + 5;
const int nax = 2e5 + 5;
int n, m, a, b, czas, ile, iles;
int wejscie[nax], ojc[nax], low[nax], stos[nax], mozna[nax];
bool bylo[nax], bylo2[nax], punkt[nax], czy_cykl[nax];
vector<int> v[nax], dwuspojne[nax], path, cykl;
int dfs(int x) {
  ++czas;
  int ile_syn = 0;
  wejscie[x] = low[x] = czas;
  bylo[x] = true;
  for (auto i : v[x]) {
    if (!bylo[i]) {
      ++ile_syn;
      ojc[i] = x;
      low[x] = min(low[x], dfs(i));
    } else if (i != ojc[x])
      low[x] = min(low[x], wejscie[i]);
  }
  if (!ojc[x])
    punkt[x] = ile_syn > 1;
  else
    for (auto i : v[x])
      if (ojc[i] == x && low[i] >= wejscie[x]) punkt[x] = true;
  return low[x];
}
bool dfs2(int x, int f, int kt) {
  bylo[x] = true;
  stos[ile++] = x;
  for (auto i : v[x])
    if (i != f && mozna[i] == kt) {
      if (bylo[i]) {
        int wsk = ile - 1;
        while (stos[wsk] != i) {
          cykl.push_back(stos[wsk]);
          czy_cykl[stos[wsk]] = true;
          --wsk;
        }
        czy_cykl[i] = true;
        cykl.push_back(i);
        return true;
      } else if (dfs2(i, x, kt))
        return true;
    }
  return false;
}
bool swaguj(int x, int f, int rozne, int kt) {
  path.push_back(x);
  bylo2[x] = true;
  if (czy_cykl[x]) return true;
  for (auto i : v[x])
    if (!bylo2[i] && mozna[i] == kt && i != f && i != rozne) {
      if (swaguj(i, x, rozne, kt)) return true;
    }
  path.pop_back();
  return false;
}
bool find_path(int x, int prawo, int lewo, int kt) {
  for (auto i : v[x])
    if (mozna[i] == kt && i != prawo && i != lewo) {
      path.push_back(x);
      if (!swaguj(i, x, x, kt)) {
        puts("BLAD");
        printf("z %d wychodzi do %d\n", x, i);
        puts("znalazlem cykl");
        for (auto i : cykl) printf("%d ", i);
        puts("");
        for (auto i : dwuspojne[kt]) printf("%d ", i);
        puts("");
      }
      return true;
    }
  return false;
}
bool check(int kt) {
  ile = 0;
  cykl.clear();
  path.clear();
  for (auto i : dwuspojne[kt]) mozna[i] = kt;
  if (kt)
    for (auto i : dwuspojne[kt - 1]) bylo[i] = czy_cykl[i] = bylo2[i] = false;
  if (!dfs2(dwuspojne[kt][0], 0, kt)) return false;
  int dl = (int)cykl.size();
  for (int i = 0; i <= (dl)-1; ++i)
    if (find_path(cykl[i], cykl[(i + 1) % dl], cykl[(i - 1 + dl) % dl], kt)) {
      puts("YES");
      printf("%d", (int)path.size());
      for (auto j : path) printf(" %d", j);
      puts("");
      int wsk = i;
      int ile = 0;
      while (cykl[wsk] != path.back()) {
        wsk = (wsk + 1) % dl;
        ++ile;
      }
      printf("%d", ile + 1);
      for (int j = i; cykl[j] != path.back(); j = (j + 1) % dl)
        printf(" %d", cykl[j]);
      printf(" %d\n", path.back());
      printf("%d", dl - ile + 1);
      for (int j = i; cykl[j] != path.back(); j = (j - 1 + dl) % dl)
        printf(" %d", cykl[j]);
      printf(" %d\n", path.back());
      return true;
    }
  return false;
}
void dfs4(int x) {
  dwuspojne[iles].push_back(x);
  for (auto i : v[x])
    if (ojc[i] == x && low[i] < wejscie[x]) dfs4(i);
}
void dfs3(int x) {
  if (!ojc[x] || punkt[x]) {
    for (auto i : v[x])
      if (ojc[i] == x && low[i] == wejscie[x]) {
        dwuspojne[iles].push_back(x);
        dfs4(i);
        ++iles;
      }
  }
  for (auto i : v[x])
    if (ojc[i] == x) dfs3(i);
}
int main(int argc, char* argv[]) {
  scanf("%d%d", &n, &m);
  for (int i = 0; i <= (m)-1; ++i) {
    scanf("%d%d", &a, &b);
    v[a].push_back(b);
    v[b].push_back(a);
  }
  for (int i = 1; i <= n; ++i)
    if (!bylo[i]) {
      dfs(i);
      dfs3(i);
    }
  for (int i = 1; i <= n; ++i) mozna[i] = -1;
  for (int i = 1; i <= n; ++i) bylo[i] = false;
  for (int i = 0; i <= (iles)-1; ++i) {
    if (check(i)) return 0;
  }
  puts("NO");
  debug = argc > 1;
  return 0;
}
