#include<bits/stdc++.h>
#define ll long long
#define pll pair<ll, ll>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ld long double
using namespace std;
struct point
{
ll x, y;
point operator + (const point & p) const
{
return point{x+p.x, y+p.y};
}
point operator - (const point & p) const
{
return point{x-p.x, y-p.y};
}
long long cross(const point & p) const
{
return x*p.y - y*p.x;
}
bool operator < (const point & p) const
{
if (x!=p.x) return x<p.x;
return y<p.y;
}
bool operator == (const point & p) const
{
return x==p.x && y==p.y;
}
};
void reorder_polygon(vector <point> & P)
{
ll pos=0;
for(ll i=1; i<P.size(); i++)
if(P[i].y<P[pos].y || (P[i].y==P[pos].y && P[i].x<P[pos].x))
pos = i;
rotate(P.begin(), P.begin() + pos, P.end());
}
vector <point> minkowski(vector<point> P, vector<point> Q)
{
// the first vertex must be the lowest
reorder_polygon(P);
reorder_polygon(Q);
// we must ensure cyclic indexing
P.push_back(P[0]);
P.push_back(P[1]);
Q.push_back(Q[0]);
Q.push_back(Q[1]);
// main part
vector<point> result;
ll i=0, j=0;
while(i<P.size()-2 || j<Q.size()-2)
{
result.push_back(P[i]+Q[j]);
auto cross=(P[i+1]-P[i]).cross(Q[j+1]-Q[j]);
if(cross>=0 && i<P.size()-2) i++;
if(cross<=0 && j<Q.size()-2) j++;
}
return result;
}
bool ccw(point a, point b, point c)
{
ll v=a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y);
return v>0;
}
vector <point> CVH(vector <point> a)
{
ll n=a.size();
sort(a.begin(), a.end());
vector <point> cvh;
cvh.pb(a[0]); cvh.pb(a[1]);
for (ll i=2; i<n; i++)
{
while (cvh.size()>1 && !ccw(cvh[cvh.size()-2], cvh[cvh.size()-1], a[i]))
cvh.pop_back();
cvh.pb(a[i]);
}
for (ll i=n-2; i>=0; i--)
{
if (a[i]==cvh[cvh.size()-2] || a[i]==cvh.back())
continue;
while (cvh.size()>1 && !ccw(cvh[cvh.size()-2], cvh[cvh.size()-1], a[i]))
cvh.pop_back();
cvh.pb(a[i]);
}
cvh.pop_back();
return cvh;
}
const ll maxn=3e5+5;
ll ptr;
vector <point> P[maxn];
bool cmp(ll a, ll b)
{
return P[a].size()<P[b].size();
}
bool check[maxn], check2[maxn];
ll pa[maxn], dep[maxn];
vector <ll> A[maxn];
ll U[maxn], V[maxn], a[maxn], b[maxn];
priority_queue <ll, vector <ll>, function<bool(ll, ll)>> p(cmp);
void dfs(ll u)
{
check[u]=1;
for (ll idx:A[u])
{
if (idx==pa[u])
continue;
ll v=U[idx]==u ? V[idx] : U[idx];
if (!check[v]) dep[v]=dep[u]+1, pa[v]=idx, dfs(v);
else if (dep[v]<dep[u])
{
ll suma=a[idx], sumb=b[idx]; check2[idx]=1;
vector <pll> p; p.pb({a[idx], b[idx]});
ll crr=u;
while (crr!=v)
{
ll idxn=pa[crr], crrn=U[idxn]==crr ? V[idxn] : U[idxn];
check2[idxn]=1;
suma+=a[idxn], sumb+=b[idxn];
p.pb({a[idxn], b[idxn]}); crr=crrn;
}
for (ll i=0; i<p.size(); i++)
P[ptr].pb({suma-p[i].fi, sumb-p[i].se});
P[ptr]=CVH(P[ptr]);
ptr++;
}
}
}
int main()
{
ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ll n, m; cin >> n >> m;
for (ll i=1; i<=m; i++)
{
cin >> U[i] >> V[i] >> a[i] >> b[i];
A[U[i]].pb(i); A[V[i]].pb(i);
}
dfs(1);
for (ll i=0; i<ptr; i++)
p.push(i);
while (p.size()>=2)
{
ll u=p.top(); p.pop();
ll v=p.top();
P[v]=minkowski(P[v], P[u]);
}
ll suma=0, sumb=0;
for (ll i=1; i<=m; i++)
if (!check2[i])
suma+=a[i], sumb+=b[i];
ll ans=1e18;
if (!p.empty())
{
for (point i:P[p.top()])
ans=min(ans, (suma+i.x)*(sumb+i.y));
}
else ans=suma*sumb
cout << ans;
}