structVector { int x, y; Vector(int x_ = 0.0, int y_ = 0.0) : x(x_), y(y_){} inline Vector operator + (Vector rhs) { return Vector(x + rhs.x, y + rhs.y); } inline Vector operator - (Vector rhs) { return Vector(x - rhs.x, y - rhs.y); } inlineintoperator ^ (Vector rhs) { return x * rhs.y - y * rhs.x; } inlinebooloperator < (const Vector &rhs) const { return x * y == rhs.x * rhs.y ? x < rhs.x : x * y < rhs.x * rhs.y; } }; structedge { int frm, to, w, t, c; inlinebooloperator < (const edge &rhs) const { return w < rhs.w; } }e[maxm]; int n, m, f[maxn]; Vector ans;
intfind(int x){ return (f[x] == x) ? x : f[x] = find(f[x]); } inlineintrd(){ registerint x = 0, c = getchar(); while (!isdigit(c)) c = getchar(); while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar(); return x; } Vector kruskal(){ Vector ret(0,0); for (int i = 1; i <= n; ++i) f[i] = i; sort(e + 1, e + 1 + m); for (int i = 1; i <= m; ++i) { int fx = find(e[i].frm), fy = find(e[i].to); if (fx != fy) { ret.x += e[i].c; ret.y += e[i].t; f[fx] = fy; } } ans = min(ans, ret); return ret; } voidsolve(Vector L, Vector R){ for (int i = 1; i <= m; ++i) { e[i].w = (R.x - L.x) * e[i].t - (R.y - L.y) * e[i].c; } Vector ret = kruskal(); if (((R - L) ^ (ret - L)) >= 0) return; solve(L, ret); solve(ret, R); }
intmain(){ scanf("%d%d", &n, &m); for (int i = 1; i <= m; ++i) { e[i].frm = rd() + 1; e[i].to = rd() + 1; e[i].c = rd(); e[i].t = rd(); } ans = Vector(0x3f3f3f3f, 1); for (int i = 1; i <= m; ++i) e[i].w = e[i].t; Vector T = kruskal(); for (int i = 1; i <= m; ++i) e[i].w = e[i].c; Vector C = kruskal(); solve(C, T); printf("%d %d\n", ans.x, ans.y); return0; }