洛谷 P5540

题目链接: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 << "\n";
	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 << "\n";
}
posted @ 2020-08-31 16:32  Aliemo  阅读(113)  评论(4编辑  收藏  举报