#include <bits/stdc++.h>
const int kN = 500000 + 5;
const int INF = 0x3f3f3f3f;
int n, m;
struct Edge {
  int a, b, l, r;
};
Edge e[kN << 2];
int tot;
int dist[kN << 2];
std::vector<int> edges[kN][2];
int main() {
  scanf("%d%d", &n, &m);
  if (n == 1) return puts("0"), 0;
  for (int i = 0; i < m; ++i) {
    int a, b, l, r;
    scanf("%d%d%d%d", &a, &b, &l, &r);
    --a;
    --b;
    e[tot] = Edge{a, b, l, r};
    edges[a][0].emplace_back(tot++);
    e[tot] = Edge{a, b, l, r};
    edges[a][1].emplace_back(tot++);
    e[tot] = Edge{b, a, l, r};
    edges[b][0].emplace_back(tot++);
    e[tot] = Edge{b, a, l, r};
    edges[b][1].emplace_back(tot++);
  }
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < 2; ++j)
      std::sort(edges[i][j].begin(), edges[i][j].end(),
                [&](int a, int b) { return e[a].l > e[b].l; });
  using PQNode = std::pair<int, int>;
  std::priority_queue<PQNode, std::vector<PQNode>, std::greater<PQNode>> pq;
  memset(dist, INF, sizeof(dist));
  for (int i = 0; i < n; ++i) {
    for (int u : edges[i][0]) {
      if (e[u].a == 0 && e[u].l == 0) {
        dist[u] = 0;
        pq.emplace(0, u);
      }
    }
  }
  while (!pq.empty()) {
    int d, u;
    std::tie(d, u) = pq.top();
    pq.pop();
    if (d != dist[u]) continue;
    int val = dist[u] + 1;
    auto &vec = edges[e[u].b][val & 1];
    while (!vec.empty()) {
      int v = vec.back();
      if (val > e[v].r) {
        vec.pop_back();
        continue;
      }
      if (e[u].r < e[v].l) break;
      int go = std::max(val, e[v].l);
      if ((go - val) % 2) ++go;
      if (go > e[u].r) break;
      if (dist[v] > go) {
        dist[v] = go;
        pq.emplace(go, v);
      }
      vec.pop_back();
    }
  }
  int result = INF;
  for (int i = 0; i < tot; ++i)
    if (e[i].a == n - 1) result = std::min(result, dist[i]);
  if (result == INF) result = -1;
  printf("%d\n", result);
}
