#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N; long long R;
if (!(cin >> N >> R)) return 0;
vector<vector<int>> adj(N+1);
vector<vector<char>> adjMat(N+1, vector<char>(N+1, 0));
for (long long i = 0; i < R; ++i) {
int a,b; cin >> a >> b;
if (!adjMat[a][b]) {
adj[a].push_back(b);
adj[b].push_back(a);
adjMat[a][b] = adjMat[b][a] = 1;
}
}
if (N < 4) { cout << "NO\n"; return 0; }
vector<char> isNeighbor(N+1, 0);
const int UNVIS = -1;
for (int s = 1; s <= N; ++s) {
int deg = adj[s].size();
if (deg < 2) continue;
// mark neighbors of s
fill(isNeighbor.begin(), isNeighbor.end(), 0);
for (int u : adj[s]) isNeighbor[u] = 1;
// multi-source BFS init
vector<int> dist(N+1, UNVIS), src(N+1, -1), prev(N+1, -1);
queue<int> q;
for (int u : adj[s]) {
dist[u] = 0;
src[u] = u;
prev[u] = -1;
q.push(u);
}
while (!q.empty()) {
int cur = q.front(); q.pop();
for (int to : adj[cur]) {
if (to == s) continue; // remove s
// do not step into other neighbors of s (they are allowed only as sources)
if (isNeighbor[to] && src[cur] != to) continue;
if (dist[to] == UNVIS) {
dist[to] = dist[cur] + 1;
src[to] = src[cur];
prev[to] = cur;
q.push(to);
} else if (src[to] != src[cur]) {
// Found meeting between two different sources a = src[cur], b = src[to]
int a = src[cur], b = src[to];
// build path from a -> ... -> cur
vector<int> p1;
int x = cur;
while (x != -1) { p1.push_back(x); if (x == a) break; x = prev[x]; }
if (p1.back() != a) continue; // safety
reverse(p1.begin(), p1.end()); // now a ... cur
// build path from b -> ... -> to
vector<int> p2;
x = to;
while (x != -1) { p2.push_back(x); if (x == b) break; x = prev[x]; }
if (p2.back() != b) continue;
reverse(p2.begin(), p2.end()); // now b ... to
// Construct cycle: s, p1 (a..cur), then reverse of p2 (to..b)
vector<int> cycle;
cycle.push_back(s);
for (int node : p1) cycle.push_back(node);
// append reversed p2 (from 'to' down to 'b')
for (int i = (int)p2.size()-1; i >= 0; --i) cycle.push_back(p2[i]);
// sanity: all nodes must be distinct
vector<char> seen(N+1, 0);
bool okDistinct = true;
for (int node : cycle) {
if (seen[node]) { okDistinct = false; break; }
seen[node] = 1;
}
if (!okDistinct) continue;
int k = cycle.size();
if (k < 4) continue;
// verify it's an induced cycle: no extra edges between non-consecutive vertices
bool induced = true;
for (int i = 0; i < k && induced; ++i) {
for (int j = i+1; j < k; ++j) {
if ( (j == i+1) || (i==0 && j==k-1) ) continue; // consecutive in cycle
if (adjMat[cycle[i]][cycle[j]]) { induced = false; break; }
}
}
if (!induced) continue;
// success: print cycle
for (int i = 0; i < k; ++i) {
if (i) cout << ' ';
cout << cycle[i];
}
cout << '\n';
return 0;
}
}
}
}
cout << "no\n";
return 0;
}