二维最小乘积生成树模板

曾经的博客:
https://blog.csdn.net/cold_chair/article/details/77200459

板题:
https://www.luogu.com.cn/problem/P5540

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int N = 10005;

int n, m;

struct nod {
	int u, v;
	int x, y, w1, w2;
} a[N];

struct P {
	int x, y;
	P(int _x = 0, int _y = 0) {
		x = _x, y = _y;
	}
};

int cmp(nod a, nod b) {
	return a.w1 == b.w1 ? a.w2 < b.w2 : a.w1 < b.w1;
}

int f[N];

int F(int x) { return f[x] == x ? x : (f[x] = F(f[x]));}

int cho[N];

int ans = 1e9, ans1, ans2;

P kk() {
	sort(a + 1, a + m + 1, cmp);
	fo(i, 1, n) f[i] = i;
	P s = P(0, 0);
	int se = 0;
	fo(i, 1, m) {
		if(F(a[i].u) != F(a[i].v)) {
			cho[i] = 1;
			f[f[a[i].u]] = f[a[i].v];
			s.x += a[i].x;
			s.y += a[i].y;
		} else cho[i] = 0;
	}
	if(s.x * s.y < ans || (s.x * s.y == ans && s.x < ans1)) {
		ans = s.x * s.y;
		ans1 = s.x; ans2 = s.y;
	}
	return s;
}

void dg(int x1, int y1, int x2, int y2) {
	if(x1 == y1 && x2 == y2) return;
	fo(i, 1, m) {
		a[i].w1 = -((y2 - y1) * a[i].x + (x1 - x2) * a[i].y);
		a[i].w2 = 0;
	}
	P p = kk();
	int x3 = p.x, y3 = p.y;
	if((x2 - x3) * (y1 - y3) - (y2 - y3) * (x1 - x3) <= 0) return;
	dg(x1, y1, x3, y3);
	dg(x3, y3, x2, y2);
}

int main() {
	scanf("%d %d", &n, &m);
	fo(i, 1, m) {
		scanf("%d %d %d %d", &a[i].u, &a[i].v, &a[i].x, &a[i].y);
		a[i].u ++, a[i].v ++;
	}
	fo(i, 1, m) {
		a[i].w1 = a[i].x;
		a[i].w2 = a[i].y;
	}
	P st = kk();
	fo(i, 1, m) {
		a[i].w1 = a[i].y;
		a[i].w2 = a[i].x;
	}
	P en = kk();
	dg(st.x, st.y, en.x, en.y);
	pp("%d %d\n", ans1, ans2);
}
posted @ 2020-08-05 16:34  Cold_Chair  阅读(223)  评论(0编辑  收藏  举报