#include <bits/stdc++.h>
using namespace std;
inline void read(int& buf) {
  buf = 0;
  char c = getchar();
  while (!isdigit(c)) c = getchar();
  while (isdigit(c)) {
    buf = buf * 10 + c - '0';
    c = getchar();
  }
}
const int INF = 0x3f3f3f3f;
const int maxn = 3000 + 3;
vector<int> G[maxn];
int dist[maxn][maxn], n, m;
bool done[maxn], already[maxn][maxn];
struct Node {
  int idx, len;
  Node(int a, int b) : idx(a), len(b) {}
  bool operator<(const Node& rhs) const { return len > rhs.len; }
};
vector<Node> first[maxn], last[maxn];
struct heap_node {
  int d, u;
  heap_node(int a, int b) : d(a), u(b) {}
  bool operator<(const heap_node& rhs) const { return d > rhs.d; }
};
priority_queue<heap_node> q;
void dijkstra(int s) {
  for (int i = 1; i <= n; i++) dist[s][i] = INF;
  dist[s][s] = 0;
  memset(done, 0, sizeof(done));
  while (!q.empty()) q.pop();
  q.push(heap_node(0, s));
  while (!q.empty()) {
    heap_node x = q.top();
    q.pop();
    int u = x.u;
    if (done[u]) continue;
    done[u] = true;
    int bound = G[u].size();
    for (int i = 0; i < bound; i++) {
      int to = G[u][i];
      if (dist[s][to] > dist[s][u] + 1) {
        dist[s][to] = dist[s][u] + 1;
        q.push(heap_node(dist[s][to], to));
      }
    }
  }
}
int ans[5];
void solve() {
  int total = 0;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) {
      if (i == j || dist[i][j] == INF) continue;
      int buf = dist[i][j], size_1 = first[i].size(), size_2 = last[j].size();
      int bound_1 = min(3, size_1);
      int bound_2 = min(3, size_2);
      for (int ww_1 = 0; ww_1 < bound_1; ww_1++)
        for (int ww_2 = 0; ww_2 < bound_2; ww_2++) {
          int idx_1 = first[i][ww_1].idx, len_1 = first[i][ww_1].len;
          int idx_2 = last[j][ww_2].idx, len_2 = last[j][ww_2].len;
          if (idx_1 == idx_2 || idx_1 == i || idx_1 == j || idx_2 == i ||
              idx_2 == j)
            continue;
          if (total < buf + len_1 + len_2) {
            total = buf + len_1 + len_2;
            ans[1] = idx_1;
            ans[2] = i;
            ans[3] = j;
            ans[4] = idx_2;
          }
        }
    }
  printf("%d %d %d %d\n", ans[1], ans[2], ans[3], ans[4]);
}
int main() {
  read(n);
  read(m);
  for (int i = 1; i <= n; i++) {
    G[i].clear();
    first[i].clear();
    last[i].clear();
    for (int j = 1; j <= n; j++) already[i][j] = false;
  }
  while (m--) {
    int a, b;
    read(a);
    read(b);
    if (!already[a][b]) {
      G[a].push_back(b);
      already[a][b] = true;
    }
  }
  for (int i = 1; i <= n; i++) dijkstra(i);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (i != j && dist[j][i] < INF) first[i].push_back(Node(j, dist[j][i]));
      if (i != j && dist[i][j] < INF) last[i].push_back(Node(j, dist[i][j]));
    }
    sort(first[i].begin(), first[i].end());
    sort(last[i].begin(), last[i].end());
  }
  solve();
  return 0;
}
