#include <bits/stdc++.h>
using namespace std;
inline void In(long long _, ...) {
  va_list lis;
  va_start(lis, _);
  while (_--) scanf("%lld", va_arg(lis, long long *));
}
inline void Out(long long _, ...) {
  va_list lis;
  va_start(lis, _);
  while (_--) printf("%lld\n", va_arg(lis, long long));
}
inline void Out_(long long _, ...) {
  va_list lis;
  va_start(lis, _);
  while (_--) printf("%lld ", va_arg(lis, long long));
}
const int N = 3005, M = 5005, INF = 0x3f3f3f3f;
long long n, m, tot;
long long head[N], dis[N][N];
struct Node {
  long long u, d;
  bool operator<(const Node &tmp) const { return d > tmp.d; }
};
vector<Node> ve[N], vec[N];
struct Edge {
  long long nxt, to, w;
} e[M];
void add_edge(long long u, long long v, long long w, int flag) {
  e[++tot] = (Edge){head[u], v, w};
  head[u] = tot;
  if (flag) add_edge(v, u, w, 0);
}
void print() {
  for (int(i) = (1); (i) <= (n); ++(i)) Out(ve[i][0].d);
}
queue<int> q;
void Floyd() {
  for (int(x) = (1); (x) <= (n); ++(x)) {
    q.push(x);
    dis[x][x] = 0;
    while (q.size()) {
      long long u = q.front();
      q.pop();
      for (int(i) = head[(u)]; (i); (i) = e[(i)].nxt) {
        long long v = e[i].to;
        if (dis[x][v] == INF) {
          dis[x][v] = dis[x][u] + 1;
          q.push(v);
        }
      }
    }
  }
  for (int(i) = (1); (i) <= (n); ++(i))
    for (int(j) = (1); (j) <= (n); ++(j)) {
      if (dis[j][i] != INF) ve[i].push_back((Node){j, dis[j][i]});
      if (dis[i][j] != INF) vec[i].push_back((Node){j, dis[i][j]});
    }
  for (int(i) = (1); (i) <= (n); ++(i)) sort(ve[i].begin(), ve[i].end());
  for (int(i) = (1); (i) <= (n); ++(i)) sort(vec[i].begin(), vec[i].end());
  Node node_a[6], node_d[6];
  long long ans = 0, ansa, ansb, ansc, ansd;
  for (int(b) = (1); (b) <= (n); ++(b)) {
    for (int(c) = (1); (c) <= (n); ++(c)) {
      if (b == c || dis[b][c] == INF) continue;
      long long dis_ab = 0, dis_cd = 0;
      long long tmpa = 0, tmpd = 0;
      int cnta = 0, cntd = 0;
      for (int i = 0; i < (int)ve[b].size() && i <= 3; ++i) {
        if (ve[b][i].u == b || ve[b][i].u == c) continue;
        node_a[++cnta] = ve[b][i];
      }
      for (int i = 0; i < (int)vec[c].size() && i <= 3; ++i) {
        if (vec[c][i].u == b || vec[c][i].u == c) continue;
        node_d[++cntd] = vec[c][i];
      }
      for (int(i) = (1); (i) <= (cnta); ++(i)) {
        for (int(j) = (1); (j) <= (cntd); ++(j)) {
          if (node_a[i].u != node_d[j].u &&
              dis_ab + dis_cd < node_a[i].d + node_d[j].d) {
            tmpa = node_a[i].u;
            tmpd = node_d[j].u;
            dis_ab = node_a[i].d;
            dis_cd = node_d[j].d;
          }
        }
      }
      if (dis_ab && dis_cd && dis[b][c] + dis_ab + dis_cd > ans) {
        ans = dis[b][c] + dis_ab + dis_cd;
        ansa = tmpa;
        ansb = b;
        ansc = c;
        ansd = tmpd;
      }
    }
  }
  Out_(4, ansa, ansb, ansc, ansd);
}
int main() {
  In(2, &n, &m);
  for (int(i) = (1); (i) <= (n); ++(i))
    for (int(j) = (1); (j) <= (n); ++(j)) dis[i][j] = INF;
  for (int(i) = (1); (i) <= (m); ++(i)) {
    long long u, v;
    In(2, &u, &v);
    add_edge(u, v, 1, 0);
  }
  Floyd();
}
