usingnamespacestd; #define ll long long #define pii pair<int, int> constint N = 1e6 + 10; constint mod = 1e9 + 7;
intread() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar(); return x * f; }
structLCT { #define ls son[pos][0] #define rs son[pos][1]
int fa[N], cnt[N], root, tcnt; pii mx[N], val[N]; int son[N][2]; int rev[N]; voidpushup(int pos) { mx[pos] = max(max(mx[rs], mx[ls]), val[pos]); } boolisroot(int pos) { return pos != son[fa[pos]][0] && pos != son[fa[pos]][1]; } voidaddtag(int pos) { rev[pos] ^= 1; swap(son[pos][0], son[pos][1]); } voidpushdown(int pos) { if (rev[pos]) { if (son[pos][1]) addtag(son[pos][1]); if (son[pos][0]) addtag(son[pos][0]); rev[pos] = 0; } }
voidconect(int x, int d, int y) { son[x][d] = y; fa[y] = x; }
voidrotate(int x) { int y = fa[x], z = fa[y], dx = isson(x), dy = isson(y);
fa[x] = z; if (!isroot(y)) son[z][dy] = x; //conect(z, dy, x); conect(y, dx, son[x][dx ^ 1]); conect(x, dx ^ 1, y); pushup(y), pushup(x); } int st[N]; voidsplay(int x) { int top; st[top = 1] = x; int u = x; while (!isroot(u)) u = fa[u], st[++top] = u; while (top) pushdown(st[top--]); while (!isroot(x)) { int y = fa[x]; if (isroot(y)) { rotate(x); } elseif (isson(x) == isson(y)) rotate(y), rotate(x); else rotate(x), rotate(x); } pushup(x); } voidaccess(int x) {
for (int i = 0; x; i = x, x = fa[x]) {
splay(x), son[x][1] = i, pushup(x); } } voidmakeroot(int x) { access(x), splay(x), addtag(x); // access 之后将没有右子树。然后把x变成根,把下面都翻转,这样x就是最小的元素了。 } intfindroot(int x) { access(x), splay(x); while (son[x][0]) pushdown(x), x = son[x][0]; //splay(x); return x; } voidsplit(int x, int y) { makeroot(x); access(y); splay(y); } boollink(int x, int y) { makeroot(x); if (findroot(y) == x) return0; //两点已经在同一子树中,再连边不合法 fa[x] = y; return1; } boolislink(int x, int y) { makeroot(x); if (findroot(y) == x) return1; else return0; } boolcut(int x, int y) { makeroot(x); if (findroot(y) == x) { split(x, y); if (fa[x] == y && !son[x][1]) { fa[x] = 0; son[y][0] = 0; //x在findroot(y)后被转到了根 pushup(y); } return0; } return1; }
} t;
structnode { int u, v, a, b; } e[N]; intmain() { int n = read(), m = read(); for (int i = 1; i <= m; i++) { e[i].u = read(), e[i].v = read(), e[i].a = read(), e[i].b = read(); } sort(e + 1, e + 1 + m, [&](node x, node y) { return x.a < y.a; }); for (int i = 1; i <= m; i++) t.val[i + n] = {e[i].b, i}; int ans = 1e9; for (int i = 1; i <= m; i++) { int u = e[i].u, v = e[i].v, a = e[i].a, b = e[i].b; if (t.islink(u, v)) { t.split(u, v); pii o = t.mx[v]; if (o.first > b) { t.cut(e[o.second].u, o.second + n); t.cut(e[o.second].v, o.second + n); t.link(u, i + n); t.link(v, i + n); } } else { t.link(u, i + n); t.link(v, i + n); } if (t.islink(1, n)) { t.split(1, n); // cout << t.mx[n].first << endl; ans = min(ans, a + t.mx[n].first); } } if (ans == 1e9) cout << -1 << endl; else cout << ans << endl; }