#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int x = 0, fu = 0;
  char ch = getchar();
  for (; ch < 48 || ch > 57; ch = getchar()) fu |= (ch == '-');
  for (; ch > 47 && ch < 58; ch = getchar()) x = x * 10 + ch - '0';
  return fu ? -x : x;
}
int n, m, head[500005][2], eot;
struct edge {
  int t, nxt, R;
} e[2000005];
void add(int u, int v, int R, int op) {
  e[++eot] = (edge){v, head[u][op], R};
  head[u][op] = eot;
}
struct node {
  int u, v, l, r;
  node(int U = 0, int V = 0, int L = 0, int R = 0) : u(U), v(V), l(L), r(R) {}
  inline bool operator<(const node &B) const { return l < B.l; }
} tmp;
multiset<node> s;
multiset<node>::iterator it;
int L[500005][2];
int main() {
  n = read(), m = read();
  if (n == 1) return puts("0"), 0;
  for (int i = 1, u, v, l, r; i <= m; i++) {
    u = read(), v = read(), l = read(), r = read() - 1;
    s.insert(node(u, v, l, r - ((r - l) & 1)));
    s.insert(node(u, v, l + 1, r - !((r - l) & 1)));
    s.insert(node(v, u, l, r - ((r - l) & 1)));
    s.insert(node(v, u, l + 1, r - !((r - l) & 1)));
  }
  memset(L, -1, sizeof(L)), L[1][0] = 0;
  while (!s.empty()) {
    it = s.begin();
    tmp = (*it);
    s.erase(it);
    if (tmp.l > tmp.r) continue;
    if (L[tmp.u][tmp.l & 1] >= tmp.l) {
      if (tmp.v == n) return printf("%d\n", tmp.l + 1), 0;
      int x = tmp.v, l = tmp.l + 1, r = tmp.r + 1, op = (tmp.l & 1) ^ 1;
      L[x][op] = max(L[x][op], r);
      for (int i = head[x][op]; i; i = e[i].nxt) {
        s.insert(node(x, e[i].t, l, e[i].R));
      }
      head[x][op] = 0;
    } else
      add(tmp.u, tmp.v, tmp.r, tmp.l & 1);
  }
  puts("-1");
  return 0;
}
