一维排序 另一维lct维护最小生成树
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int ch[150010][2],rv[150010],fa[150010],st[150010],tp;
int ma[150010],x[150010],nu[150010],mn[150010];
int n,m;
int head[50010];
int ans = 0x3f3f3f3f;
struct edge {
int u,v,a,b;
bool operator < (const edge &b)const {
return a < b.a;
}
}e[100010];
int read_int () {
char c = getchar();
int re = 0;
for(;c > '9' || c < '0';c = getchar());
for(;c >= '0' && c <= '9';c = getchar())
re = re * 10 + c - '0';
return re;
}
int find (int u) {
if(head[u] == u)
return u;
return head[u] = find(head[u]);
}
void pu (int u) {
ma[u] = x[u];
mn[u] = nu[u];
if(ma[u] < ma[ch[u][0]]) {
ma[u] = ma[ch[u][0]];
mn[u] = mn[ch[u][0]];
}
if(ma[u] < ma[ch[u][1]]) {
ma[u] = ma[ch[u][1]];
mn[u] = mn[ch[u][1]];
}
}
void reverse (int u) {
int t = ch[u][0];
ch[u][0] = ch[u][1];
ch[u][1] = t;
rv[u] ^= 1;
}
void pd (int u) {
if(!rv[u])
return;
rv[u] = 0;
reverse(ch[u][0]);
reverse(ch[u][1]);
}
void rot (int u,int d) {
ch[fa[u]][d ^ 1] = ch[u][d];
if(ch[u][d])
fa[ch[u][d]] = fa[u];
int t = fa[fa[u]];
fa[fa[u]] = u;
ch[u][d] = fa[u];
fa[u] = t;
pu(ch[u][d]);
pu(u);
if(!t)
return;
if(ch[t][0] == ch[u][d])
ch[t][0] = u;
if(ch[t][1] == ch[u][d])
ch[t][1] = u;
}
void splay (int u) {
st[tp = 1] = u;
int t = u;
while(ch[fa[t]][0] == t || ch[fa[t]][1] == t) {
t = fa[t];
st[++tp] = t;
}
while(tp)
pd(st[tp--]);
while(ch[fa[u]][0] == u || ch[fa[u]][1] == u) {
if(ch[fa[fa[u]]][0] != fa[u] && ch[fa[fa[u]]][1] != fa[u]) {
if(ch[fa[u]][0] == u)
rot(u,1);
else rot(u,0);
}
else {
int d = ch[fa[fa[u]]][0] == fa[u];
if(ch[fa[u]][d] == u) {
rot(u,d ^ 1);
rot(u,d);
}
else {
rot(u,d);
rot(u,d);
}
}
}
}
void access (int u) {
int v = 0;
while(u) {
splay(u);
ch[u][1] = v;
pu(u);
v = u;
u = fa[u];
}
}
void mtr (int u) {
access(u);
splay(u);
reverse(u);
}
void link (int u,int v) {
mtr(u);
mtr(v);
fa[v] = u;
}
void cut (int u,int v) {
mtr(u);
access(u);
splay(v);
fa[v] = 0;
}
int main () {
n = read_int();
m = read_int();
for(int i = 1;i <= n;++i)
head[i] = i;
for(int i = 1;i <= m;++i) {
e[i].u = read_int();
e[i].v = read_int();
e[i].a = read_int();
e[i].b = read_int();
}
sort(e + 1,e + 1 + m);
e[0].a = e[1].a;
for(int i = 1;i <= m + 1;++i) {
if(e[i].a != e[i - 1].a && find(1) == find(n)) {
mtr(1);
access(n);
splay(1);
ans = min(ans,e[i - 1].a + ma[1]);
}
if(i == m + 1)
break;
if(e[i].u == e[i].v)
continue;
if(find(e[i].u) == find(e[i].v)) {
mtr(e[i].u);
access(e[i].v);
splay(e[i].u);
if(ma[e[i].u] < e[i].b)
continue;
int t = mn[e[i].u];
cut(t + n,e[t].v);
cut(t + n,e[t].u);
}
else head[find(e[i].u)] = find(e[i].v);
x[i + n] = ma[i + n] = e[i].b;
nu[i + n] = mn[i + n] = i;
link(i + n,e[i].u);
link(i + n,e[i].v);
}
if(ans == 0x3f3f3f3f)
ans = -1;
printf("%d\n",ans);
return 0;
}