#include <bits/stdc++.h>
using namespace std;
const int N = 2 * 1e5 + 100;
int n, m, de[N], fa[N][21], vi[N], up[N];
int tot, first[N], nxt[N * 2], point[N * 2];
vector<int> e[N], p[N];
struct node {
  int wh[2];
  inline void upd(int x) {
    if (x == -1) return;
    if (wh[0] == -1 || up[x] < up[wh[0]])
      wh[1] = wh[0], wh[0] = x;
    else if (wh[1] == -1 || up[x] < up[wh[1]])
      wh[1] = x;
  }
} low[N];
inline int read() {
  int f = 1, x = 0;
  char s = getchar();
  while (s < '0' || s > '9') {
    if (s == '-') f = -1;
    s = getchar();
  }
  while (s >= '0' && s <= '9') {
    x = x * 10 + s - '0';
    s = getchar();
  }
  return x * f;
}
inline void add_edge(int x, int y) {
  nxt[++tot] = first[x];
  first[x] = tot;
  point[tot] = y;
}
void print(vector<int> ans) {
  printf("%d ", (int)ans.size());
  for (int i = 0; i < (int)ans.size(); i++) printf("%d ", ans[i]);
  printf("\n");
}
inline int lca(int a, int b) {
  if (de[a] > de[b]) swap(a, b);
  for (int i = 20; i >= 0; i--)
    if (de[fa[b][i]] >= de[a]) b = fa[b][i];
  if (a == b) return a;
  for (int i = 20; i >= 0; i--)
    if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
  return fa[a][0];
}
inline int find(int u, int x) {
  for (int i = 20; i >= 0; i--)
    if (de[fa[u][i]] > de[x]) u = fa[u][i];
  return u;
}
void dfs(int x, int father) {
  vi[x] = 1;
  fa[x][0] = father;
  for (int i = first[x]; i != -1; i = nxt[i]) {
    int u = point[i];
    if (u == fa[x][0]) continue;
    if (vi[u]) {
      p[x].push_back(u);
      continue;
    }
    e[x].push_back(u);
    de[u] = de[x] + 1;
    dfs(u, x);
  }
}
void dfs1(int x) {
  vi[x] = 1;
  for (int i = 0; i < (int)e[x].size(); i++) {
    int u = e[x][i];
    dfs1(u);
    low[x].upd(low[u].wh[0]);
    low[x].upd(low[u].wh[1]);
  }
  up[x] = de[x];
  for (int i = 0; i < (int)p[x].size(); i++) {
    int u = p[x][i];
    up[x] = min(up[x], de[u]);
  }
  low[x].upd(x);
  for (int i = 0; i < (int)p[x].size(); i++) {
    int u = p[x][i], v;
    if (de[u] < de[x]) continue;
    v = find(u, x);
    if (low[v].wh[0] == -1) continue;
    assert(low[v].wh[0] != low[v].wh[1]);
    int a = x, b = u,
        c = ((low[v].wh[0] == u && up[low[v].wh[0]] == de[x]) ? low[v].wh[1]
                                                              : low[v].wh[0]),
        d;
    if (c == -1 || up[c] > de[x]) continue;
    for (int j = 0; j < (int)p[c].size(); j++) {
      if (de[p[c][j]] < de[x]) {
        d = p[c][j];
        break;
      }
      if (de[p[c][j]] == de[x] && b != c) {
        d = p[c][j];
        break;
      }
    }
    int LCA = lca(b, c);
    printf("YES\n");
    vector<int> ans;
    ans.push_back(a);
    while (b != LCA) ans.push_back(b), b = fa[b][0];
    ans.push_back(LCA);
    print(ans);
    ans.clear();
    while (a != d) ans.push_back(a), a = fa[a][0];
    ans.push_back(d);
    while (c != LCA) ans.push_back(c), c = fa[c][0];
    if (ans.back() != LCA) ans.push_back(LCA);
    print(ans);
    ans.clear();
    while (LCA != x) ans.push_back(LCA), LCA = fa[LCA][0];
    ans.push_back(x);
    reverse(ans.begin(), ans.end());
    print(ans);
    exit(0);
  }
}
signed main() {
  tot = -1;
  memset(first, -1, sizeof(first));
  n = read();
  m = read();
  for (int i = 1; i <= m; i++) {
    int u = read(), v = read();
    add_edge(u, v);
    add_edge(v, u);
  }
  for (int i = 1; i <= n; i++)
    if (!vi[i]) dfs(i, i);
  for (int j = 1; j <= 20; j++)
    for (int i = 1; i <= n; i++) fa[i][j] = fa[fa[i][j - 1]][j - 1];
  memset(vi, 0, sizeof(vi));
  memset(low, -1, sizeof(low));
  for (int i = 1; i <= n; i++)
    if (!vi[i]) dfs1(i);
  printf("NO\n");
}
