#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int MOD = 1e9 + 7;
const int N = 3e3 + 10;
int n;
template <class T>
bool maximize(T &x, T y) {
  if (x < y)
    x = y;
  else
    return 0;
  return 1;
}
struct graph {
  vector<int> v[N];
  int good[N][3], rgood[N][3];
  int d[N][N], q[N];
  void BFS(int st) {
    d[st][st] = 1;
    int top = 1, bot = 1;
    q[1] = st;
    while (top <= bot) {
      int x = q[top++];
      for (auto y : v[x])
        if (!d[st][y]) {
          d[st][y] = d[st][x] + 1;
          q[++bot] = y;
        }
    }
    for (auto i = (bot); i >= (max(bot - 2, 2)); i--) good[st][bot - i] = q[i];
  }
  void solve() {
    for (auto i = (1); i <= (n); i++) BFS(i);
    for (auto i = (1); i <= (n); i++) {
      for (auto x = (1); x <= (n); x++) {
        if (x != i && d[x][i] > d[rgood[i][2]][i]) {
          rgood[i][2] = x;
          for (auto j = (2); j >= (1); j--)
            if (d[rgood[i][j]][i] > d[rgood[i][j - 1]][i])
              swap(rgood[i][j], rgood[i][j - 1]);
        }
      }
    }
    int ans = 0;
    vector<int> asel;
    for (auto s2 = (1); s2 <= (n); s2++)
      for (auto s3 = (1); s3 <= (n); s3++)
        if (s2 != s3 && d[s2][s3]) {
          for (auto j = (0); j <= (2); j++) {
            int s1 = rgood[s2][j];
            if (!d[s1][s2] || s1 == s3) continue;
            for (auto i = (0); i <= (2); i++) {
              int s4 = good[s3][i];
              if (!d[s3][s4] || s4 == s1 || s4 == s2) continue;
              if (maximize(ans, d[s1][s2] + d[s2][s3] + d[s3][s4]))
                asel = {s1, s2, s3, s4};
            }
          }
        }
    for (auto i : asel) cout << i << " ";
  }
} mgr;
void prepare() {
  int m, x, y;
  scanf("%d%d", &n, &m);
  while (m--) {
    scanf("%d%d", &x, &y);
    mgr.v[x].push_back(y);
  }
}
int main() {
  prepare();
  mgr.solve();
}
