POJ-3565 二分图——km算法

题目链接:

http://poj.org/problem?id=3565


题目大意:

在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标。让每只蚂蚁去一棵苹果树,

一棵苹果树对应一只蚂蚁。这样就有N条直线路线,问:怎样分配,才能使总路程和最小,且

N条线不相交。


思路:

用一个图来说明思路。


假设A、B为蚂蚁,C、D为苹果树。则存在两种匹配:第一种是AD、BC,第二种是AC、BD。

根据三角形不等式AD+BC < AC+BD,最后得到很重要的一个性质——满足总路程之和最小

的方案一定不相交。现在来构建二分图,一边为蚂蚁,另一边为苹果树,以距离为边权值,题

目就变为了求带权二分图最小权和的最佳匹配。反向来思考,将距离乘以-1取负值建图,那

就变为了求带权二分图最大权和的最佳匹配。直接用KM算法来做。  

KM::点击打开链接


AC代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int qwq = 0x3f3f3f;
double w[110][110], x[110], y[110];
double xx, yy;
double usex[1000], usey[1000], cx[110], cy[110];
int n,line[110], kk[110];
bool finds(int u)
{
	usex[u] = 1;
	for (int i = 1; i <= n; i++)
	{
		if (!usey[i] && fabs(cx[u] + cy[i]-w[u][i]) <1e-5)
		{
			usey[i] = 1;
			if (!line[i] || finds(line[i]))
			{
				line[i] = u;
				return true;
			}
		}
	}
	return false;
}
void km() 
{
	memset(line, 0, sizeof(line));
	for (int i = 1; i <= n; i++)
	{
		while (1) {
			memset(usex, 0, sizeof(usex));
			memset(usey, 0, sizeof(usey));
			if (finds(i))break;
			double d = qwq;
			for (int j = 1; j <= n; j++)
			{
				if (usex[j])
				{
					for (int k = 1; k <= n; k++)
					{
						if (!usey[k])
						{
							d = min(d, cx[j] + cy[k] - w[j][k]);
						}
					}
				}
			}
			for (int j = 1; j <= n; j++)
			{
				if (usex[j])
					cx[j] -= d;
			}
			for (int j = 1; j <= n; j++)
			{
				if (usey[j])
					cy[j] += d;
			}
		}
	}
	for (int i = 1; i <= n; i++)
	{
		kk[line[i]] = i;
	}
	for (int i = 1; i <= n; i++)
	{
		cout << kk[i] << endl;
	}
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> x[i] >> y[i];
	}
	memset(w, 0, sizeof(w));
	for (int i = 1; i <= n; i++)
	{

		cin >> xx >> yy;
		for (int j = 1; j <= n; j++)
		{
			w[j][i] = -sqrt((x[j] - xx)*(x[j] - xx) + (y[j] - yy)*(y[j] - yy));
		}
	}
	for (int i = 1; i <= n; i++)
	{
		double d = -qwq;
		for (int j = 1; j <= n; j++)
		{
			d = max(d, w[i][j]);

		}
		cx[i] = d;
		cy[i] = 0;
	}
	km();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/80724713