#include <bits/stdc++.h>
const int N = 5e5 + 1000;
int n, m;
std::tuple<int, int, int, int> edge[N];
void init() {
  std::cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    int u, v;
    int t[2];
    scanf("%d%d%d%d", &u, &v, &t[0], &t[1]);
    edge[i] = std::make_tuple(u, v, t[0], t[1]);
  }
}
void work() {
  static std::vector<std::tuple<int, int, int>> edge_vec[2][N];
  for (int i = 1; i <= m; i++) {
    int u, v;
    int t[2];
    std::tie(u, v, t[0], t[1]) = edge[i];
    for (int j = 0; j <= 1; j++) {
      edge_vec[j][u].push_back(
          std::make_tuple(t[0] + (t[0] % 2 != j), v, t[1]));
      edge_vec[j][v].push_back(
          std::make_tuple(t[0] + (t[0] % 2 != j), u, t[1]));
    }
  }
  for (int i = 0; i <= 1; i++) {
    for (int j = 1; j <= n; j++) {
      std::sort(edge_vec[i][j].begin(), edge_vec[i][j].end(),
                std::greater<std::tuple<int, int, int>>());
    }
  }
  static int answer[N];
  std::memset(answer, -1, sizeof(answer));
  std::priority_queue<std::tuple<int, int, int>,
                      std::vector<std::tuple<int, int, int>>,
                      std::greater<std::tuple<int, int, int>>>
      heap;
  heap.push(std::make_tuple(0, 1, 0));
  while (!heap.empty()) {
    int u, t[2];
    std::tie(t[0], u, t[1]) = heap.top();
    if (t[0] % 2 != t[1] % 2) {
      t[1]--;
    }
    heap.pop();
    if (answer[u] == -1) {
      answer[u] = t[0];
    }
    int parity = t[0] & 1;
    while (!edge_vec[parity][u].empty()) {
      int v, t_next[2];
      std::tie(t_next[0], v, t_next[1]) = edge_vec[parity][u].back();
      if (t_next[0] <= t[1]) {
        if (std::max(t_next[0] + 1, t[0] + 1) <= t_next[1]) {
          heap.push(
              std::make_tuple(std::max(t_next[0] + 1, t[0] + 1), v, t_next[1]));
        }
        edge_vec[parity][u].pop_back();
      } else {
        break;
      }
    }
  }
  std::cout << answer[n] << std::endl;
}
int main() {
  init();
  work();
  return 0;
}
