题目链接:P5540 最小乘积生成树
题目大意
题目中已经描述的很清楚了/笑哭
solution
艹,不会
参考自:solution
code:
/**
* Author: Alieme
* Data: 2020.8.30
* Problem: P5540
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 100010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
struct UFS {
int fa[MAXN];
inline void init(int n) {for(rr int i = 1; i <= n; i++) fa[i] = i;}
int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
inline bool check(int x, int y) {return find(x) == find(y);}
inline void merge(int x, int y) {x = find(x), y = find(y); if (x != y) fa[x] = y;}
}S;
struct Gragh {
int u, v, a, b, w;
bool operator < (const Gragh &b) const {return w < b.w;}
}g[MAXN];
struct Point {
int x, y;
Point() {}
Point(int X, int Y) {x = X, y = Y;}
Point operator -(const Point &b) const { return Point(x - b.x, y - b.y);}
};
int n, m;
Point ans = Point(inf, inf);
inline int cross(Point a, Point b) {return a.x * b.y - a.y * b.x;}
inline Point kruskal() {
Point res = Point(0, 0);
int tot = 0;
sort(g + 1, g + 1 + m);
S.init(n);
for (rr int i = 1; i <= m; i++) {
int u = g[i].u, v = g[i].v, a = g[i].a, b = g[i].b;
if (S.check(u, v)) continue;
S.merge(u, v);
res.x += a;
res.y += b;
tot++;
if (tot == n - 1) break;
}
int sum = ans.x * ans.y, now = res.x * res.y;
// cout << sum << " " << now << "
";
if (sum > now || (sum == now && ans.x > res.x)) ans = res;
return res;
}
void solve(Point A, Point B) {
for (rr int i = 1; i <= m; i++) g[i].w = g[i].b * (B.x - A.x) + g[i].a * (A.y - B.y);
Point C = kruskal();
if (cross(B - A, C - A) >= 0) return ;
solve(A, C);
solve(C, B);
}
signed main() {
n = read();
m = read();
for (rr int i = 1; i <= m; i++) {
g[i].u = read() + 1;
g[i].v = read() + 1;
g[i].a = read();
g[i].b = read();
}
for (rr int i = 1; i <= m; i++) g[i].w = g[i].a;
Point A = kruskal();
for (rr int i = 1; i <= m; i++) g[i].w = g[i].b;
Point B = kruskal();
solve(A, B);
cout << ans.x << " " << ans.y << "
";
}