structEdge { int x, y; LL c, t, val; booloperator <(const Edge &t) const { return val < t.val; } }; structPoint { LL x, y; Point() {} Point(LL _x, LL _y) : x(_x), y(_y) {} booloperator <(const Point &t) const { return x * y == t.x * t.y ? x < t.x : x * y < t.x * t.y; } Point operator -(const Point &t) const { return Point(x - t.x, y - t.y); } LL operator *(const Point &t) const { return x * t.y - y * t.x; } };
int n, m; Point ans; int fa[N]; Edge e[N];
intfind(int x){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
inline Point Kruskal(){ Point re(0, 0); sort(e+1, e+m+1); for (int i = 1; i <= n; ++i) fa[i] = i; for (int i = 1; i <= m; ++i) { int x = find(e[i].x), y = find(e[i].y); if (x != y) { fa[x] = y; re.x += e[i].c, re.y += e[i].t; } } return re; }
// l: P, r: Q, mid: S voidsolve(Point l, Point r){ for (int i = 1; i <= m; ++i) e[i].val = e[i].t * (r.x - l.x) - e[i].c * (r.y - l.y); Point mid = Kruskal(); if ((mid - l) * (r - l) <= 0) return; ans = min(ans, mid); solve(l, mid), solve(mid, r); }
inlinevoidmain(){ read(n), read(m); for (int i = 1, u, v; i <= m; ++i) { read(u), read(v), read(e[i].c), read(e[i].t); e[i].x = u + 1, e[i].y = v + 1; } for (int i = 1; i <= m; ++i) e[i].val = e[i].c; Point l = Kruskal(); for (int i = 1; i <= m; ++i) e[i].val = e[i].t; Point r = Kruskal(); ans = min(l, r); solve(l, r); printf("%lld %lld\n", ans.x, ans.y); } }