/*
写了个傻逼二分套二分,真的傻逼了,我这tmd是在贪心呐,70分满满的人品
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 50010
using namespace std;
int head[maxn],num,n,m,mx1,mx2,mid1,mid2,ans=0x7fffffff;
bool vis[maxn],ok[100010];
struct node{int to,pre,v1,v2;}e[200010];
struct Node{int from,to,v1,v2;}edge[100010];
void Insert(int from,int to,int v1,int v2){
e[++num].to=to;
e[num].v1=v1;
e[num].v2=v2;
e[num].pre=head[from];
head[from]=num;
}
void bfs(){
queue<int>q;
q.push(1);vis[1]=1;
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i;i=e[i].pre){
int to=e[i].to;
if(!vis[to]){vis[to]=1;q.push(to);}
}
}
}
bool check1(){
memset(vis,0,sizeof(vis));
memset(ok,0,sizeof(ok));
memset(head,0,sizeof(head));num=0;
for(int i=1;i<=m;i++){
if(edge[i].v1>mid1)continue;
Insert(edge[i].from,edge[i].to,edge[i].v1,edge[i].v2);
Insert(edge[i].to,edge[i].from,edge[i].v1,edge[i].v2);
ok[i]=1;
}
bfs();
return vis[n];
}
bool check2(){
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));num=0;
for(int i=1;i<=m;i++){
if((edge[i].v2>mid2)||(!ok[i]))continue;
Insert(edge[i].from,edge[i].to,edge[i].v1,edge[i].v2);
Insert(edge[i].to,edge[i].from,edge[i].v1,edge[i].v2);
}
bfs();
return vis[n];
}
int main(){
freopen("magicalforest11.in","r",stdin);//freopen("magicalforest.out","w",stdout);
scanf("%d%d",&n,&m);
int x,y,z,c;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&x,&y,&z,&c);
edge[i].from=x;edge[i].to=y;edge[i].v1=z;edge[i].v2=c;
Insert(x,y,z,c);Insert(y,x,z,c);
mx1=max(mx1,z);
mx2=max(mx2,c);
}
bfs();
if(!vis[n]){puts("-1");return 0;}
int l1=1,r1=mx1;
while(l1<=r1){
mid1=(l1+r1)>>1;
if(check1()){
int l2=1,r2=mx2;
while(l2<=r2){
mid2=(l2+r2)>>1;
if(check2())r2=mid2-1,ans=min(ans,mid1+mid2);
else l2=mid2+1;
}
r1=mid1-1;
}
else l1=mid1+1;
}
printf("%d",ans);
return 0;
}