#include <bits/stdc++.h>

#define NS (205)
#define MS (10005)

using namespace std;

typedef long long LL;

template<typename _Tp> inline void IN(_Tp &dig)
{
char c; bool flag = 0; dig = 0;
while (c = getchar(), !isdigit(c)) if (c == '-') flag = 1;
while (isdigit(c)) dig = dig * 10 + c - '0', c = getchar();
if (flag) dig = -dig;
}

LL M[2][2]; // 基底

struct vec
{
LL x, y;
vec() { x = y = 0; }
vec(const LL a, const LL b) { x = a, y = b; }
bool operator != (const vec oth) const { return x != oth.x || y != oth.y; }
vec operator - (const vec oth)
{
return vec(x - oth.x, y - oth.y);
}
void operator += (const vec oth)
{
x += oth.x, y += oth.y;
}
int crs(const vec oth) { return x * oth.y - y * oth.x; } // 叉乘
void trans() // 变换
{
LL a, b;
a = x * M[0][0] + y * M[1][0];
b = x * M[0][1] + y * M[1][1];
x = a, y = b;
}
void untrans() // 逆变换
{
LL a, b, c = M[0][0] * M[1][1] - M[0][1] * M[1][0];
a = (M[1][1] * x - M[1][0] * y) / c;
b = (M[0][0] * y - M[0][1] * x) / c;
x = a, y = b;
}
} ans(1000000, 1000000);

void update(const vec a) // 尝试更新答案
{
if (a.x * a.y < ans.x * ans.y) ans = a;
else if (a.x < ans.x && a.x * a.y == ans.x * ans.y) ans = a;
}

int n, m;

struct edge // 边
{
int a, b;
vec v;
bool operator < (const edge oth) const
{
return v.x < oth.v.x; // 找横坐标最小的点
}
} E[MS];

int f[NS]; // 并查集

int findf(int a) { return f[a] == a ? a : f[a] = findf(f[a]); }

vec run(vec bx, vec by) // bx, by 组成一组基底
{
M[0][0] = bx.x, M[0][1] = bx.y;
M[1][0] = by.x, M[1][1] = by.y;
for (int i = 1; i <= n; i += 1) f[i] = i;
for (int i = 1; i <= m; i += 1) E[i].v.trans(); // 对整个空间进行变换
sort(E + 1, E + 1 + m); // 最小生成树
vec res;
for (int i = 1, j = 1; i <= m && j < n; i += 1)
{
int fa = findf(E[i].a), fb = findf(E[i].b);
if (fa == fb) continue;
j++, res += E[i].v, f[fa] = fb;
}
for (int i = 1; i <= m; i += 1) E[i].v.untrans(); // 逆变换回来，撤销操作
res.untrans(); // 返回原空间的向量
return res;
}

void hull(vec s, vec t) // quick hull 找凸包
{
vec i = t - s, k = run(vec(-i.y, i.x), i), j = k - s;
if (j.crs(i) <= 0) return; // 已经没有凸出去的点了就返回
update(k), hull(s, k), hull(k, t);
}

int main(int argc, char const* argv[])
{
IN(n), IN(m);
for (int i = 1; i <= m; i += 1)
{
IN(E[i].a), IN(E[i].b), IN(E[i].v.x), IN(E[i].v.y);
E[i].a++, E[i].b++;
}
vec s = run(vec(1, 0), vec(0, 1));
vec t = run(vec(0, -1), vec(1, 0));
update(s), update(t);
if (s != t) hull(s, t);
printf("%lld %lld\n", ans.x, ans.y);
return 0;
}


#### Remmina

No puzzle that couldn't be solved.