#include <bits/stdc++.h>
using namespace std;
const int maxn = 200005;
int n, m, flag, cnt, head[maxn], val[maxn], dep[maxn], from[maxn], to[maxn],
    tot, fa[maxn], now, aa, bb, d[maxn], top, f[maxn], l1, l2, r1, r2, s, st,
    en;
struct edge {
  int to, next;
} e[maxn << 1];
void print() {
  printf("%d ", top);
  for (int i = 1; i <= top; ++i) printf("%d ", d[i]);
  puts("");
}
void add(int x, int y) {
  e[cnt].to = y;
  e[cnt].next = head[x];
  head[x] = cnt++;
}
void prepare(int u, int pre) {
  dep[u] = dep[pre] + 1;
  fa[u] = pre;
  for (int i = head[u]; i; i = e[i].next) {
    if (e[i].to == pre) continue;
    if (!dep[e[i].to])
      prepare(e[i].to, u);
    else if (dep[e[i].to] < dep[u])
      f[e[i].to]--, f[u]++;
  }
  f[pre] += f[u];
}
void dfs2(int u, int pre) {
  for (int i = head[u]; i; i = e[i].next) {
    if (dep[e[i].to] == dep[u] + 1) {
      dfs2(e[i].to, u);
      if (l2) return;
    } else if (dep[e[i].to] < dep[s] && e[i].to != fa[u]) {
      if (l1)
        r2 = u, l2 = e[i].to;
      else
        r1 = u, l1 = e[i].to;
      if (l2) return;
    }
  }
}
void ad(int l, int r) {
  int k = top;
  top += abs(dep[r] - dep[l]) + 1;
  if (dep[l] > dep[r])
    for (int i = l, j = k + 1; j <= top; i = fa[i], ++j) d[j] = i;
  else
    for (int i = r, j = top; j > k; i = fa[i], --j) d[j] = i;
}
int main() {
  scanf("%d%d", &n, &m);
  cnt = 1;
  for (int i = 1; i <= m; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    add(x, y);
    add(y, x);
  }
  for (int i = 1; i <= n; ++i)
    if (!dep[i]) prepare(i, 0);
  s = 0;
  for (int i = 1; i <= n; ++i) {
    if (f[i] > 1) {
      s = i;
      break;
    }
  }
  l1 = l2 = r1 = r2 = 0;
  if (!s) {
    puts("NO");
    return 0;
  }
  puts("YES");
  dfs2(s, 0);
  if (dep[l1] > dep[l2]) swap(l1, l2), swap(r1, r2);
  for (st = r1, en = r2; st != en;)
    dep[st] > dep[en] ? st = fa[st] : en = fa[en];
  top = 0;
  ad(st, r1);
  ad(l1, l2);
  print();
  top = 0;
  ad(st, r2);
  ad(l2, l2);
  print();
  top = 0;
  ad(st, l2);
  print();
}
