1 #include <algorithm>
2 #include <iostream>
3 #include <cstring>
4 #include <cstdio>
5 #include <cctype>
6
7 inline void read(int & x)
8 {
9 x = 0;
10 int k = 1;
11 char c = getchar();
12 while (!isdigit(c))
13 if (c == ‘-‘) c = getchar(), k = -1;
14 else c = getchar();
15 while (isdigit(c))
16 x = (x << 1) + (x << 3) + (c ^ 48),
17 c = getchar();
18 x *= k;
19 }
20
21 const int N = 505050, inf = 2147483645;
22 int n, m, tot, rt = 0, x, y, A, B, z, top = 0, ans = inf, stk_top = 0, cur;
23 int faz[N], siz[N], sma[N], tag[N], val[N], cnt[N], son[N][2], fa[N], stk[N], L[N], R[N];
24
25 inline int min(const int &a, const int &b)
26 {
27 return a > b ? b : a;
28 }
29
30 inline void Swap(int &a, int &b)
31 {
32 a ^= b, b ^= a, a ^= b;
33 }
34
35 inline int Root(int u)
36 {
37 return son[faz[u]][0] != u && son[faz[u]][1] != u;
38 }
39
40 inline int Getson(int u)
41 {
42 return son[faz[u]][1] == u;
43 }
44
45 inline void Pushup(int u)
46 {
47 sma[u] = u;
48 if (val[sma[u]] < val[sma[son[u][0]]]) sma[u] = sma[son[u][0]];
49 if (val[sma[u]] < val[sma[son[u][1]]]) sma[u] = sma[son[u][1]];
50 }
51
52 inline void Pushdown(int u)
53 {
54 if (!tag[u]) return;
55 tag[son[u][0]] ^= 1,
56 tag[son[u][1]] ^= 1,
57 Swap(son[u][0], son[u][1]);
58 tag[u] = 0;
59 }
60
61 inline int New(int x)
62 {
63 int u = ++tot;
64 siz[u] = cnt[u] = 1,
65 son[u][0] = tag[u] =
66 faz[u] = son[u][1] = 0,
67 val[u] = x, sma[u] = u;
68 return u;
69 }
70
71 inline void Ratate(int u)
72 {
73 int y = faz[u], z = faz[y], ch = Getson(u), b = son[u][ch ^ 1];
74 Pushdown(y), Pushdown(u);
75 if (!Root(y)) son[z][Getson(y)] = u;
76 son[u][ch ^ 1] = y, son[y][ch] = b,
77 faz[u] = z, faz[b] = y, faz[y] = u;
78 Pushup(y), Pushup(u);
79 }
80
81 inline void Splay(int u)
82 {
83 int cur = u;
84 stk[stk_top = 1] = u;
85 while (!Root(u)) stk[++stk_top] = u = faz[u];
86 while (stk_top) Pushdown(stk[stk_top--]);
87 while (!Root(cur))
88 {
89 if (!Root(faz[cur]))
90 if (Getson(cur) == Getson(faz[cur])) Ratate(faz[cur]);
91 else Ratate(cur);
92 Ratate(cur);
93 }
94 }
95
96 inline void Access(int u)
97 {
98 for (int ch = 0; u; u = faz[ch = u])
99 Splay(u), son[u][1] = ch, Pushup(u);
100 }
101
102 inline void Mkrt(int u)
103 {
104 Access(u), Splay(u), tag[u] ^= 1;
105 }
106
107 inline void Split(int x, int y)
108 {
109 Mkrt(x), Access(y), Splay(y);
110 }
111
112 inline void Link(int a, int b)
113 {
114 Mkrt(a), faz[a] = b;
115 }
116
117 inline void Cut(int a, int b)
118 {
119 Split(a, b);
120 if (son[b][0] != a || faz[a] != b) return;
121 faz[a] = 0, son[b][0] = 0;
122 Pushup(b);
123 }
124
125 inline int Get(int a, int b)
126 {
127 Split(b, a);
128 return sma[a];
129 }
130
131 struct Edge
132 {
133 int u, v, a, b;
134 bool operator < (const Edge &B) const
135 { return a < B.a; }
136 }e[505050];
137
138 int Find(int u)
139 {
140 return fa[u] == u ? u : fa[u] = Find(fa[u]);
141 }
142
143 inline void Uni(int a, int b)
144 {
145 int r1 = Find(a),
146 r2 = Find(b);
147 if (r1 == r2) return;
148 fa[r1] = r2;
149 }
150
151 inline bool Tgt(int a, int b)
152 {
153 int r1 = Find(a),
154 r2 = Find(b);
155 if (r1 == r2) return true;
156 return false;
157 }
158
159 signed main()
160 {
161 // freopen("a.in", "r", stdin);
162 // freopen("a.out", "w", stdout);
163 read(n), read(m);
164 for (int i = 1; i <= n; ++i)
165 fa[i] = i;
166 for (int i = 1; i <= m; ++i)
167 read(e[i].u), read(e[i].v),
168 read(e[i].a), read(e[i].b);
169 // puts("");
170 std::sort(e + 1, e + m + 1);
171 for (int i = 1; i <= m; ++i)
172 {
173 if (Tgt(e[i].u, e[i].v))
174 {
175 if (val[z = Get(e[i].u, e[i].v)] > e[i].b)
176 Cut(e[z - n].u, z),
177 Cut(z, e[z - n].v);
178 else
179 {if (Tgt(1, n))
180 ans = min(ans, val[Get(1, n)] + e[i].a);
181 continue;
182 }
183 }
184 else Uni(e[i].u, e[i].v);
185 val[n + i] = e[i].b,
186 sma[n + i] = n + i,
187 Link(e[i].u, n + i),
188 Link(n + i, e[i].v);
189 if (Tgt(1, n))
190 ans = min(ans, val[Get(1, n)] + e[i].a);
191 }
192 if (ans == inf) puts("-1");
193 else printf("%d\n", ans);
194 return 0;
195 }