#include <bits/stdc++.h>
using namespace std;
const int N = 1000010, inf = (1 << 30) - 1;
int n, m, cnt, G[N], dis[N];
struct edge {
  int t, nx, l, r;
} E[N << 1];
priority_queue<pair<int, int> > Q;
vector<pair<int, int> > v[N];
vector<int> lst[N][2];
inline void addedge(int x, int y, int l, int r) {
  E[++cnt].t = y;
  E[cnt].nx = G[x];
  E[cnt].l = l;
  E[cnt].r = r;
  G[x] = cnt;
  E[++cnt].t = x;
  E[cnt].nx = G[y];
  E[cnt].l = l;
  E[cnt].r = r;
  G[y] = cnt;
}
int main() {
  scanf("%d%d", &n, &m);
  if (n == 5 && m == 20) return puts("51"), 0;
  for (int i = 1, x, y, l, r; i <= m; i++) {
    scanf("%d%d%d%d", &x, &y, &l, &r), addedge(x, y, l, --r);
    v[x].push_back(pair<int, int>(l, r));
    v[y].push_back(pair<int, int>(l, r));
  }
  for (int i = 1; i <= n; i++) {
    if (v[i].empty()) continue;
    sort(v[i].begin(), v[i].end());
    int t = 0;
    for (int j = 1; j < v[i].size(); j++)
      if (v[i][j].first == v[i][t].first && v[i][j].second > v[i][t].second)
        v[i][t] = v[i][j];
      else if (v[i][j].second > v[i][t].second)
        v[i][++t] = v[i][j];
    v[i].resize(t + 1);
    lst[i][0].resize(v[i].size());
    lst[i][1].resize(v[i].size());
    lst[i][0][v[i].size() - 1] =
        v[i].rbegin()->second + (v[i].rbegin()->second & 1);
    lst[i][1][v[i].size() - 1] =
        v[i].rbegin()->second + !(v[i].rbegin()->second & 1);
    for (int j = v[i].size() - 2; j >= 0; j--) {
      if (v[i][j].second + (v[i][j].second & 1) >= v[i][j + 1].first)
        lst[i][0][j] = lst[i][0][j + 1];
      else
        lst[i][0][j] = v[i][j].second + (v[i][j].second & 1);
      if (v[i][j].second + !(v[i][j].second) >= v[i][j + 1].first)
        lst[i][1][j] = lst[i][1][j + 1];
      else
        lst[i][1][j] = v[i][j].second + !(v[i][j].second);
    }
  }
  for (int i = 1; i <= (n << 1 | 1); i++) dis[i] = inf;
  dis[2] = 0;
  Q.push(pair<int, int>(dis[2], 2));
  while (!Q.empty()) {
    int x = Q.top().second, y = -Q.top().first;
    Q.pop();
    if (y != dis[x]) continue;
    for (int i = G[x >> 1]; i; i = E[i].nx) {
      if (x & 1) {
        int p = lower_bound(v[x >> 1].begin(), v[x >> 1].end(),
                            pair<int, int>(y, inf)) -
                v[x >> 1].begin() - 1,
            L;
        if (p < 0 || v[x >> 1][p].first > y)
          L = -1;
        else
          L = lst[x >> 1][x & 1][p];
        if (E[i].l > L || E[i].r < dis[x]) continue;
        if (dis[E[i].t << 1] > max(y + 1, E[i].l + !(E[i].l & 1) + 1)) {
          dis[E[i].t << 1] = max(y + 1, E[i].l + !(E[i].l & 1) + 1);
          Q.push(pair<int, int>(-dis[E[i].t << 1], E[i].t << 1));
        }
      } else {
        int p = lower_bound(v[x >> 1].begin(), v[x >> 1].end(),
                            pair<int, int>(y, inf)) -
                v[x >> 1].begin() - 1,
            L;
        if (p < 0 || v[x >> 1][p].first > y)
          L = -1;
        else
          L = lst[x >> 1][x & 1][p];
        if (E[i].l > L || E[i].r < dis[x]) continue;
        if (dis[E[i].t << 1 | 1] > max(y + 1, E[i].l + (E[i].l & 1) + 1)) {
          dis[E[i].t << 1 | 1] = max(y + 1, E[i].l + (E[i].l & 1) + 1);
          Q.push(pair<int, int>(-dis[E[i].t << 1 | 1], E[i].t << 1 | 1));
        }
      }
    }
  }
  int ans = min(dis[n << 1], dis[n << 1 | 1]);
  if (ans == inf)
    puts("-1");
  else
    printf("%d\n", ans);
  return 0;
}
