#include <bits/stdc++.h>
using namespace std;

// 定义常量
const int MAXN = 40005;     // 节点数量上限
const int MAXM = 100005;    // 边数量上限 (每条无向边拆分为两有向边)
const long long INF = 1e18;

// 边的结构体
struct Edge {
    int to;     // 目标节点
    int weight; // 边权重
    int next;   // 下一条边的索引
} edges[MAXM * 2];

// 头指针数组
int head_arr[MAXN];
int edge_cnt = 0;

// 添加一条有向边
void add_edge(int u, int v, int w){
    edges[edge_cnt].to = v;
    edges[edge_cnt].weight = w;
    edges[edge_cnt].next = head_arr[u];
    head_arr[u] = edge_cnt++;
}

// Dijkstra 函数，返回从 start 到 node1 的最短距离，排除 blocked_edge1 和 blocked_edge2
long long dijkstra(int start, int node1, int blocked_edge1, int blocked_edge2, int n){
    // 使用距离数组和版本号来避免每次都清零
    static long long dist_arr[MAXN];
    // static int visited_version[MAXN];
    // static int current_version = 0;
    // current_version++;

    // 初始化距离
    for(int i = 1; i <= n; ++i){
        dist_arr[i] = INF;
    }
    dist_arr[start] = 0;

    // 优先队列 (距离, 节点)
    priority_queue<pair<long long, int>, vector<pair<long long, int>>, std::greater<pair<long long, int>>> pq;
    pq.emplace(0, start);

    while(!pq.empty()){
        auto [current_dist, u] = pq.top();
        pq.pop();

        if(u == node1){
            return current_dist;
        }

        if(current_dist > dist_arr[u]){
            continue;
        }

        // 遍历所有出边
        for(int e = head_arr[u]; e != -1; e = edges[e].next){
            // 如果这条边被阻断，则跳过
            if(e == blocked_edge1 || e == blocked_edge2){
                continue;
            }

            int v = edges[e].to;
            long long w = edges[e].weight;

            if(dist_arr[v] > dist_arr[u] + w){
                dist_arr[v] = dist_arr[u] + w;
                pq.emplace(dist_arr[v], v);
            }
        }
    }

    return INF;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    // 初始化头指针数组
    memset(head_arr, -1, sizeof(head_arr));

    int n, m;
    cin >> n >> m;

    // 存储节点1的所有连接边
    // 每个元素是 pair<有向边的索引，(v, w1)>
    vector<pair<int, pair<int, int>>> node1_edges;

    for(int i = 0; i < m; ++i){
        int u, v, w1, w2;
        cin >> u >> v >> w1 >> w2;

        // 添加两条有向边
        add_edge(u, v, w1); // 边编号: edge_cnt -1
        add_edge(v, u, w2); // 边编号: edge_cnt -1

        // 如果 u 是1，记录这条边
        if(u == 1){
            node1_edges.emplace_back(edge_cnt -2, make_pair(v, w1));
        }
        // 如果 v 是1，记录这条边
        if(v == 1){
            node1_edges.emplace_back(edge_cnt -2, make_pair(u, w2));
        }
    }

    long long answer = INF;

    // 遍历节点1的所有出边
    for(auto &[edge_idx, vp] : node1_edges){
        int v = vp.first;
        int w1 = vp.second;

        // 阻断这条无向边的两个有向边
        // 由于添加边时，边 idx 是偶数，后面的边是对应的另一方向
        int blocked_edge1 = edge_idx;
        int blocked_edge2 = edge_idx + 1;

        // 运行 Dijkstra 从 v 到 node1，排除 blocked_edge1 和 blocked_edge2
        long long path_dist = dijkstra(v, 1, blocked_edge1, blocked_edge2, n);

        if(path_dist != INF){
            answer = min(answer, (long long)w1 + path_dist);
        }
    }

    if(answer == INF){
        cout << "-1\n";
    }
    else{
        cout << answer << "\n";
    }

    return 0;
}