根本不会,调了好长时间了
#include<iostream>
#include<cstdio>
#include<vector>
#define pb push_back
using namespace std;
namespace INPUT{
char buf[1<<20],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
}
using namespace INPUT;
template<typename T>
T read(){
T x=0,p=1;
char ch=gc();
for(;ch<'0'||ch>'9';ch=gc())
if(ch=='-') p=-1;
for(;'0'<=ch&&ch<='9';ch=gc())
x=(x<<3)+(x<<1)+(ch^48);
return x*p;
}
#include<algorithm>
#define ll long long
#include<utility>
#define MP make_pair
//DSU wait for realize
template<size_t N>
struct DSU{
int fa[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
bool Union(int u,int v){
u=find(u),v=find(v);
if(u==v) return false;
fa[v]=u;
return true;
}
void init(int _n){
for(int i=1;i<=_n;i++) fa[i]=i;
}
};
template<size_t N>
struct LCT{
int f[N],ls[N],rs[N],lz[N];
pair<int,int> val[N],Max[N];//val/id
void pushup(int x){
Max[x]=val[x];
Max[x]=max(Max[x],max(Max[ls[x]],Max[rs[x]]));
}
void pushdown(int x){
if(lz[x]){
swap(ls[x],rs[x]);
if(ls[x]) lz[ls[x]]^=1;
if(rs[x]) lz[rs[x]]^=1;
lz[x]=0;
}
}
int get(int x){
if(ls[f[x]]==x) return 0;
if(rs[f[x]]==x) return 1;
return -1;
}
void connect(int x,int y,int opt){
f[x]=y;
if(opt==0) ls[y]=x;
if(opt==1) rs[y]=x;
}
void rotate(int x){
int y=f[x],z=f[y];
int opx=get(x),opy=get(y);
int u=(opx==0?rs[x]:ls[x]);
connect(u,y,opx),connect(y,x,opx^1);
connect(x,z,opy);
pushup(y),pushup(x);
}
void pushall(int x){
if(get(x)!=-1) pushall(f[x]);
pushdown(x);
}
void splay(int x){
pushall(x);
while(get(x)!=-1){
if(get(f[x])==-1) rotate(x);
else if(get(f[x])==get(x)) rotate(f[x]),rotate(x);
else rotate(x),rotate(x);
}
}
void access(int x){
int pre=0;
while(x){
splay(x),rs[x]=pre;
pushup(x);
pre=x,x=f[x];
}
}
void makeroot(int x){
access(x),splay(x);
swap(ls[x],rs[x]);
if(ls[x]) lz[ls[x]]^=1;
if(rs[x]) lz[rs[x]]^=1;
}
int findroot(int x){
access(x),splay(x);
while(ls[x]) pushdown(x),x=ls[x];
splay(x);
return x;
}
void split(int x,int y){
makeroot(x),access(y),splay(y);
}
bool link(int x,int y){
makeroot(x);
if(findroot(y)==x) return false;
f[x]=y;
return true;
}
bool cut(int x,int y){
if(findroot(x)!=findroot(y)) return false;
split(x,y);
if(f[x]!=y||rs[x]) return false;
f[x]=ls[y]=0;
pushup(x);
return true;
}
};
const int N=5e4+5;
LCT<N> lct;int tot;
DSU<N> dsu;
int n,m;
struct Edge{int u,v;int A,B;};
vector<Edge>edges;
int main(){
freopen("P2387.in","r",stdin);
freopen("P2387.out","w",stdout);
n=read<int>(),m=read<int>();
for(int i=1;i<=m;i++){
int u=read<int>(),v=read<int>();
int A=read<int>(),B=read<int>();
edges.pb({u,v,A,B});
}
sort(edges.begin(),edges.end(),[](Edge a,Edge b){
return a.A<b.A;
});
int ans=1e9+5;
dsu.init(n),tot=n;
for(auto ed:edges){
if(ed.u==ed.v) continue;
if(dsu.Union(ed.u,ed.v)){
int cur=++tot;
lct.val[cur]=MP(ed.B,cur),lct.pushup(cur);
lct.link(ed.u,cur),lct.link(ed.v,cur);
}
else {
lct.split(ed.u,ed.v);
if(lct.Max[ed.v].first>ed.B){
int cur=++tot,pre=lct.Max[ed.v].second;
lct.cut(pre,ed.u),lct.cut(pre,ed.v);
lct.val[cur]=MP(ed.B,cur),lct.pushup(cur);
lct.link(cur,ed.u),lct.link(cur,ed.v);
}
}
if(lct.findroot(1)==lct.findroot(n)) {
lct.split(1,n);
ans=min(ans,ed.A+lct.Max[n].first);
}
}
if(lct.findroot(1)!=lct.findroot(n)) puts("-1");
else printf("%d\n",ans);
}