#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;
}
// MCS (Maximum Cardinality Search)
vector<int> weight(N+1, 0);
vector<char> used(N+1, 0);
vector<int> seq; seq.reserve(N);
for (int iter = 0; iter < N; ++iter) {
int pick = -1;
int best = -1;
for (int v = 1; v <= N; ++v) if (!used[v]) {
if (weight[v] > best) { best = weight[v]; pick = v; }
}
if (pick == -1) break;
used[pick] = 1;
seq.push_back(pick);
for (int w : adj[pick]) if (!used[w]) weight[w]++;
}
// seq is selection order; reverse to get PEO candidate
reverse(seq.begin(), seq.end());
vector<int> pos(N+1, 0);
for (int i = 0; i < (int)seq.size(); ++i) pos[seq[i]] = i+1; // positions 1..N
// Check for clique property of later neighbors
for (int v = 1; v <= N; ++v) {
vector<int> later;
for (int u : adj[v]) if (pos[u] > pos[v]) later.push_back(u);
if (later.size() <= 1) continue;
// find parent = later neighbor with minimal pos (i.e., smallest index among later)
int parent = later[0];
for (int u : later) if (pos[u] < pos[parent]) parent = u;
// check all later neighbors are adjacent to parent
for (int u : later) {
if (u == parent) continue;
if (!adjMat[u][parent]) {
// Found witness: v has later neighbors parent and u not adjacent.
// BFS from parent to u using only vertices w with pos[w] >= pos[parent]
vector<int> prev(N+1, -1);
vector<char> vis(N+1, 0);
queue<int> q;
q.push(parent); vis[parent]=1; prev[parent] = -1;
while (!q.empty()) {
int cur = q.front(); q.pop();
if (cur == u) break;
for (int w : adj[cur]) {
if (!vis[w] && pos[w] >= pos[parent]) {
vis[w] = 1;
prev[w] = cur;
q.push(w);
}
}
}
if (!vis[u]) continue; // theoreticaly shouldn't happen, but safe
// reconstruct path parent -> ... -> u
vector<int> path;
for (int x = u; x != -1; x = prev[x]) path.push_back(x);
reverse(path.begin(), path.end()); // path[0] == parent, last == u
// Form cycle: v + path
// path length (nodes) >= 3 because parent and u not adjacent -> cycle length >= 4
cout << v;
for (int node : path) cout << ' ' << node;
cout << '\n';
return 0;
}
}
}
cout << "NO\n";
return 0;
}