POJ 3565 Ants (maximum weighted complete bipartite graph matching)

Topic Link

Subject to the effect:

Total plane 2 * N points, N is the number of white points, N is the number of black points. For each white point, a black point found, the two connected together with a line, requires that all the final segments do not want to pay, seeking a solution.

Meet the total sum of the minimum distance program must not intersect

See  https://blog.csdn.net/lianai911/article/details/44835659

A bipartite graph can be established, and then run the minimum weight matching KM, KM is actually running minimum weight value to the right side of the respective inverted then ran KM, then the final result is negated minimum weight.

After this question only negated running while KM, then the output match point to edge

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define mem(a, b) memset(a, b, sizeof a)
#define eps 1e-8
const int inf = 0x3f3f3f3f;
using namespace std;
const int N = 110;
struct p {
	int x, y;
	p() {

	}
	p(int x, int y) {
		this->x = x;
		this->y = y;
	}
};
p black[N], white[N];
double calculate(p& a, p& b) {
	double dx = ((double)a.x - b.x) * 1.0;
	double dy = ((double)a.y - b.y) * 1.0;
	return sqrt(dx * dx + dy * dy);
}
int n;
int match[N];
double w[N][N];
bool va[N], vb[N];
double la[N], lb[N];
double slack[N];
int res[N];
bool dfs(int x) {
	va[x] = 1;
	for (int i = 1; i <= n; i++) {
		if (!vb[i]) {
			double t = la[x] + lb[i] - w[x][i];
			if (fabs(t) < eps) {
				// ????
				vb[i] = 1;
				if (match[i] == -1 || dfs(match[i])) {
					match[i] = x;
					return 1;
				}
			}
			else if (slack[i] > t)slack[i] = t;
		}
	}
	return 0;
}
void km() {
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			w[i][j] = -calculate(black[i], white[j]);
		}
	}
	mem(match, -1);
	for (int i = 1; i <= n; i++) {
		la[i] = -1e12;
		lb[i] = 0;
		for (int j = 1; j <= n; j++) {
			if (la[i] < w[i][j])la[i] = w[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			slack[j] = 1e12;
		}
		while (1) {
			mem(va, 0);
			mem(vb, 0);
			if (dfs(i))break;
			double d = 1e12;
			for (int j = 1; j <= n; j++) {
				if (!vb[j] && d > slack[j])d = slack[j];
			}
			for (int j = 1; j <= n; j++) {
				if (va[j])la[j] -= d;
				if (vb[j])lb[j] += d;
				else slack[j] -= d;
			}
		}
	}
	mem(res, -1);
	double ans = 0;
	for (int i = 1; i <= n; i++) {
		res[match[i]] = i;
	}
	for (int i = 1; i <= n; i++) {
		cout << res[i] << "\n";
	}
}
int main()
{
	ios::sync_with_stdio(0);
	while (cin >> n) {
		for (int i = 1; i <= n; i++) {
			int x, y;
			cin >> x >> y;
			black[i].x = x;
			black[i].y = y;
		}
		for (int j = 1; j <= n; j++) {
			int x, y;
			cin >> x >> y;
			white[j].x = x;
			white[j].y = y;
		}
		km();
	}
	return 0;
}

 

Published 143 original articles · won praise 11 · views 8188

Guess you like

Origin blog.csdn.net/weixin_43701790/article/details/104033157