#include <bits/stdc++.h>
using namespace std;
struct level1 {
  long long int cost;
  long long int a, b;
  level1() { cost = -1; }
  bool operator<(const level1& a) const {
    if (a.cost == cost) {
      return true;
    } else
      return cost < a.cost;
  }
};
struct level2 {
  long long int cost;
  long long int a, b, c;
  level2() { cost = -1; }
  bool operator<(const level2& a) const {
    if (a.cost == cost) {
      return true;
    } else
      return cost < a.cost;
  }
};
struct level3 {
  long long int cost;
  long long int a, b, c, d;
  level3() { cost = -1; }
  bool operator<(const level3& a) const {
    if (a.cost == cost) {
      return true;
    } else
      return cost < a.cost;
  }
};
long long int adj[3010][3010];
long long int adjsz[3010];
long long int sp[3010][3010];
set<long long int> s;
set<level1> mem1[3010];
set<level2> mem2[3010];
level3 mem3[3010];
void bfs(long long int src) {
  queue<long long int> q;
  q.push(src);
  sp[src][src] = 0;
  while (!q.empty()) {
    long long int u = q.front();
    q.pop();
    for (long long int i = 0; i < adjsz[u]; i++) {
      long long int v = adj[u][i];
      if (sp[src][v] == -1) {
        sp[src][v] = sp[src][u] + 1;
        q.push(v);
      }
    }
  }
}
int main() {
  long long int n, m;
  memset(sp, -1, sizeof sp);
  scanf("%lld %lld", &n, &m);
  for (int i = 0; i < m; i++) {
    long long int a, b;
    scanf("%lld %lld", &a, &b);
    adj[a][adjsz[a]++] = b;
  }
  for (long long int i = 1; i <= n; i++) {
    bfs(i);
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (i != j && sp[i][j] != -1) {
        level1 vv;
        vv.cost = sp[i][j];
        vv.a = i;
        vv.b = j;
        mem1[i].insert(vv);
        if (mem1[i].size() > 5) mem1[i].erase(mem1[i].begin());
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      long long int cnt = 0;
      if (i != j && sp[i][j] != -1) {
        for (set<level1>::reverse_iterator it = mem1[j].rbegin();
             it != mem1[j].rend() && cnt < 3; it++) {
          bool flag = false;
          if (it->a == i || it->b == i) flag = true;
          if (!flag) {
            level2 toInsert;
            toInsert.cost = sp[i][j] + (*it).cost;
            toInsert.a = i;
            toInsert.b = (*it).a;
            toInsert.c = (*it).b;
            cnt++;
            mem2[i].insert(toInsert);
            if (mem2[i].size() > 3) mem2[i].erase(mem2[i].begin());
          }
        }
      }
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      if (i != j && sp[i][j] != -1) {
        for (set<level2>::reverse_iterator it = mem2[j].rbegin();
             it != mem2[j].rend(); it++) {
          level2 old = *it;
          level3 pp;
          bool flag = false;
          if (old.a == i || old.b == i || old.c == i) flag = true;
          if (flag == false) {
            pp.cost = old.cost + sp[i][j];
            pp.a = i;
            pp.b = old.a;
            pp.c = old.b;
            pp.d = old.c;
            if (pp.cost > mem3[i].cost) {
              mem3[i] = pp;
            }
            break;
          }
        }
      }
    }
  }
  int maxi = 0;
  int maxIndex = -1;
  for (int i = 1; i <= n; i++) {
    if (mem3[i].cost != -1 && maxi < mem3[i].cost) {
      maxi = mem3[i].cost;
      maxIndex = i;
    }
  }
  printf("%lld %lld %lld %lld\n", mem3[maxIndex].a, mem3[maxIndex].b,
         mem3[maxIndex].c, mem3[maxIndex].d);
}
