#include <bits/stdc++.h>
using namespace std;
const int N = 1001000;
struct node {
  int x, y, z;
  node(int x = 0, int y = 0, int z = 0) : x(x), y(y), z(z) {}
  bool operator<(const node& a) const {
    if (x != a.x) return x < a.x;
    return y < a.y;
  }
  bool operator>(const node& a) const { return a < *this; }
};
priority_queue<node, vector<node>, greater<node> > pq;
vector<node> G[N];
vector<node>::iterator fi[N];
int n, m;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  while (m-- > 0) {
    int u, v, l, r;
    cin >> u >> v >> l >> r;
    --r;
    if (l != r || !(l & 1)) {
      G[u].emplace_back(l + (l & 1), r - (r & 1), n + v);
      G[v].emplace_back(l + (l & 1), r - (r & 1), n + u);
    }
    if (l != r || (l & 1)) {
      G[n + u].emplace_back(l + !(l & 1), r - !(r & 1), v);
      G[n + v].emplace_back(l + !(l & 1), r - !(r & 1), u);
    }
  }
  for (int i = 1; i <= n * 2; ++i)
    sort(G[i].begin(), G[i].end()), fi[i] = G[i].begin();
  pq.emplace(0, 0, 1);
  while (!pq.empty()) {
    auto t = pq.top();
    pq.pop();
    if (t.z == n || t.z == n * 2) {
      cout << t.x << '\n';
      return 0;
    }
    for (auto& i = fi[t.z]; i != G[t.z].end(); ++i) {
      if (i->x > t.y) break;
      if (i->y < t.x) continue;
      pq.emplace(max(t.x, i->x) + 1, i->y + 1, i->z);
    }
  }
  cout << -1 << '\n';
  return 0;
}
