#include <bits/stdc++.h>
using namespace std;
template <typename Tk, typename Tv>
ostream& operator<<(ostream& os, const pair<Tk, Tv>& p) {
  os << "{" << p.first << ',' << p.second << "}";
  return os;
}
const int MAX = 3005;
const int MOD = 1000000000 + 7;
const int INF = 1000000;
vector<vector<int> > G;
int d[MAX][MAX], invd[MAX][MAX];
void doBFS(int start, int dist[]) {
  queue<pair<int, int> > Q;
  bool marked[MAX] = {false};
  Q.push(make_pair(start, 0));
  while (!Q.empty()) {
    pair<int, int> t = Q.front();
    Q.pop();
    int u = t.first, d = t.second;
    if (marked[u]) continue;
    marked[u] = true;
    dist[u] = d;
    for (int i = 0; i < G[u].size(); i++) {
      int v = G[u][i];
      if (!marked[v]) {
        Q.push(make_pair(v, d + 1));
      }
    }
  }
}
void init(int n) {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      d[i][j] = -INF;
    }
  }
}
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  G.resize(n);
  for (int i = 0; i < m; i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    a--, b--;
    G[a].push_back(b);
  }
  init(n);
  for (int i = 0; i < n; i++) {
    int start = i;
    doBFS(start, d[i]);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      invd[j][i] = d[i][j];
    }
  }
  vector<vector<pair<int, int> > > ds(n, vector<pair<int, int> >(n));
  vector<vector<pair<int, int> > > invds(n, vector<pair<int, int> >(n));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      ds[i][j] = make_pair(d[i][j], j);
    }
    sort(ds[i].rbegin(), ds[i].rend());
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      invds[i][j] = make_pair(invd[i][j], j);
    }
    sort(invds[i].rbegin(), invds[i].rend());
  }
  int maxSoFar = 0;
  int Answer[4] = {};
  for (int B = 0; B < n; B++) {
    for (int C = 0; C < n; C++) {
      if (B == C) continue;
      int dist = d[B][C];
      int curA = 0, curD = 0;
      while (invds[B][curA].second == C || invds[B][curA].second == B) curA++;
      while (ds[C][curD].second == B || ds[C][curD].second == C) curD++;
      if (invds[B][curA].second == ds[C][curD].second) {
        int t1 = curA + 1, t2 = curD + 1;
        while (invds[B][t1].second == C || invds[B][t1].second == B) t1++;
        while (ds[C][t2].second == B || ds[C][t2].second == C) t2++;
        int d1 = invds[B][t1].first + ds[C][curD].first;
        int d2 = invds[B][curA].first + ds[C][t2].first;
        if (d1 > d2)
          curA = t1;
        else
          curD = t2;
      }
      int maxd = dist + invds[B][curA].first + ds[C][curD].first;
      if (maxd > maxSoFar) {
        maxSoFar = maxd;
        Answer[0] = invds[B][curA].second;
        Answer[1] = B;
        Answer[2] = C;
        Answer[3] = ds[C][curD].second;
      }
    }
  }
  for (int i = 0; i < 4; i++) {
    cout << Answer[i] + 1 << " ";
  }
  cout << endl;
}
