#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
const long long INF = 1e18;
struct Edge {
int to, color, cost, idx;
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N, M;
cin >> N >> M;
vector<int> A(M), B(M), C(M), P(M);
vector<vector<Edge>> graph(N);
for (int i = 0; i < M; i++) {
cin >> A[i] >> B[i] >> C[i] >> P[i];
A[i]--; B[i]--;
graph[A[i]].push_back({B[i], C[i], P[i], i});
graph[B[i]].push_back({A[i], C[i], P[i], i});
}
vector<map<int, long long>> colorSum(N);
vector<map<int, int>> colorCount(N);
for (int i = 0; i < N; i++) {
for (const auto& e : graph[i]) {
colorCount[i][e.color]++;
colorSum[i][e.color] += e.cost;
}
}
vector<vector<pair<int, long long>>> adj(N + 2*M);
for (int i = 0; i < M; i++) {
int u = A[i], v = B[i];
int col = C[i], cost = P[i];
int edgeId1 = N + 2*i;
int edgeId2 = N + 2*i + 1;
adj[edgeId1].push_back({v, 0});
adj[edgeId2].push_back({u, 0});
if (colorCount[u][col] == 1) {
adj[u].push_back({edgeId1, 0});
} else {
long long sum = colorSum[u][col];
long long minCost = *min_element(graph[u].begin(), graph[u].end(),
[col](const Edge& a, const Edge& b) {
if (a.color != col) return false;
if (b.color != col) return false;
return a.cost < b.cost;
})->cost;
long long otherSum = sum - minCost;
adj[u].push_back({edgeId1, min((long long)cost, otherSum)});
}
if (colorCount[v][col] == 1) {
adj[v].push_back({edgeId2, 0});
} else {
long long sum = colorSum[v][col];
long long minCost = *min_element(graph[v].begin(), graph[v].end(),
[col](const Edge& a, const Edge& b) {
if (a.color != col) return false;
if (b.color != col) return false;
return a.cost < b.cost;
})->cost;
long long otherSum = sum - minCost;
adj[v].push_back({edgeId2, min((long long)cost, otherSum)});
}
}
vector<long long> dist(N + 2*M, INF);
dist[0] = 0;
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;
pq.push({0, 0});
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
if (d > dist[u]) continue;
for (const auto& [v, w] : adj[u]) {
if (dist[v] > d + w) {
dist[v] = d + w;
pq.push({dist[v], v});
}
}
}
long long ans = dist[N-1];
if (ans >= INF) {
cout << "-1\n";
} else {
cout << ans << "\n";
}
return 0;
}