#include <bits/stdc++.h>

using namespace std;

const long long N = 1e5 + 5, INF = 1e17 + 5;

long long n, m, a, b, c, d, dist[N];

bool vis[N];

struct Edge{
    long long b, c, d;
};

vector<Edge> graph[N];

long double findtime(long long t, long long wait, Edge e){
    return wait + e.c + ((e.d / (long double)(t + 1 + wait)));
}

long long findwait(long long t, Edge e){
    long long l = 0, r = INF, m1, m2;
    long double m1ans, m2ans;

    while(r - l > 2){
        m1 = l + (r - l) / 3;
        m2 = r - (r - l) / 3;

        m1ans = findtime(t, m1, e);
        m2ans = findtime(t, m2, e);

        if(m1ans <= m2ans) r = m2;
        else l = m1;
    }

    vector<pair<long double, long long>> v;

    for(long long i = l; i <= r; i++){
        v.push_back({findtime(t, i, e), i});
    }

    sort(v.begin(), v.end());

    return v.front().second;
}

void dijkstra(){
    for(int i = 1; i <= n; i++) dist[i] = INF;

    priority_queue<pair<long long, long long>> pq;

    dist[1] = 0;

    pq.push({0, 1});

    long long v;

    while(!pq.empty()){
        v = pq.top().second, pq.pop();

        if(!vis[v]){
            vis[v] = true;

            for(auto e : graph[v]){
                if(!vis[e.b]){
                    long long waitt = findwait(dist[v], e);
                    long long edget = findtime(dist[v], waitt, e);

                    if(dist[v] + edget < dist[e.b]){
                        dist[e.b] = dist[v] + edget;
                        pq.push({-dist[e.b], e.b});
                    }
                }
            }
        }
    }
}

int main(){
    ios_base::sync_with_stdio(false);cin.tie(NULL);
    
    cin >> n >> m;

    for(int i = 0; i < m; i++){
        cin >> a >> b >> c >> d;

        graph[a].push_back({b, c, d});
        graph[b].push_back({a, c, d});
    }

    dijkstra();

    cout << (dist[n] == INF ? -1 : dist[n]);
}

//================code===================//

//#define TLE

#ifdef TLE
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#endif

#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <ctime>
#include <random>
#include <chrono>
//#include <stdint.h>

#define ci(t) cin>>t
#define co(t) cout<<t
#define LL long long
#define ld long double
#define fa(i,a,b) for(LL i=(a);i<(LL)(b);++i)
#define fd(i,a,b) for(LL i=(a);i>(LL)(b);--i)
#define setp pair<int,ld>
#define setl pair<LL,LL>

#define micro 0.000000000001

using namespace std;

LL gcd(LL a, LL b)
{
	if (!(a && b)) return max(a, b);
	return a % b ? gcd(b, a % b) : b;
}

#ifdef OHSOLUTION
#define ce(t) cerr<<t
#define AT cerr << "\n=================ANS=================\n"
#define AE cerr << "\n=====================================\n"
#define DB(a) cerr << __LINE__ << ": " << #a << " = " << (a) << endl;
#define __builtin_popcount __popcnt
#define __builtin_popcountll __popcnt64
#define LLL LL
#else
#define AT
#define AE
#define ce(t)
#define LLL __int128
#endif

pair <int, int> vu[9] = { {0,1},{1,0},{0,-1} ,{-1,0},{-1,0},{-1,-1}, {0,-1} , {1,-1},{-1,-1} }; //RDLU EWSN

template<typename T, typename U> void ckmax(T& a, U b) { a = a < b ? b : a; }
template<typename T, typename U> void ckmin(T& a, U b) { a = a > b ? b : a; }
struct gcmp { bool operator()(LL a, LL b) { return a < b; } bool operator()(setl& a, setl& b) { return a.second < b.second; } };
struct lcmp { bool operator()(LL a, LL b) { return a > b; } bool operator()(setl& a, setl& b) { return a.second > b.second; } };

const int max_v = 1e5+ 7;
const int max_k = 5e2 + 7;
const int bsz = (1ll << 10) + 7;
const int INF = 1e9 + 7;
const LL LNF = (LL)5e18 + 7ll;
LL mod =  998244353;//1e9 + 7;
template<typename T, typename U> void MOD(T& a, U b) { a += b; if (a >= mod) a -= mod; };

struct node
{
	int nxt;
	int c, d;
};

vector<node> adj[max_v];

int main()
{
#ifdef OHSOLUTION
	freopen("input.txt", "r", stdin);
#endif
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int v, e; ci(v >> e);

	fa(i, 0, e)
	{
		int a, b, c, d; ci(a >> b >> c >> d); --a, --b;
		adj[a].push_back({ b,c,d });
		adj[b].push_back({ a,c,d });
	}

	vector<LL> dist(v, LNF);
	vector<bool> vist(v, 0);
	dist[0] = 0;
	priority_queue<setl, vector<setl>, lcmp> pq;
	pq.push({0,0});

	while (pq.size())
	{
		setl u;
		do
		{
			u = pq.top(); pq.pop();
		} while (pq.size() && vist[u.first]);

		if (vist[u.first]) break;

		vist[u.first] = 1;

		for (auto& v : adj[u.first])
		{
			LL base = dist[u.first]+1;		
			LL l = 0;
			LL r = 1e9 + 7;

			if (base > v.d)
			{
				if (dist[v.nxt] > dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1))
				{
					dist[v.nxt] = dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1);
					pq.push({ v.nxt,dist[v.nxt] });
				}

			}
			else
			{
				while (l < r)
				{
					LL mid = l + r >> 1;

					if ((mid + base) * (mid + base) >= v.d) r = mid;
					else l = mid + 1;
				}



				if (dist[v.nxt] > dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1))
				{
					dist[v.nxt] = dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1);
					pq.push({ v.nxt,dist[v.nxt] });
				}

				++l;

				if (dist[v.nxt] > dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1))
				{
					dist[v.nxt] = dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1);
					pq.push({ v.nxt,dist[v.nxt] });
				}

				if (l > 1)
				{
					l -= 2;
					if (dist[v.nxt] > dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1))
					{
						dist[v.nxt] = dist[u.first] + l + v.c + v.d / (dist[u.first] + l + 1);
						pq.push({ v.nxt,dist[v.nxt] });
					}
				}

			}
		}
	}

	dist[v - 1] == LNF ? co(-1) : co(dist[v - 1]);


	return 0;
}
