POJ3565Ants

Ants

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 8345 Accepted: 2651 Special Judge

Description

Young naturalist Bill studies ants in school. His ants feed on plant-louses that live on apple trees. Each ant colony needs its own apple tree to feed itself.

Bill has a map with coordinates of n ant colonies and n apple trees. He knows that ants travel from their colony to their feeding places and back using chemically tagged routes. The routes cannot intersect each other or ants will get confused and get to the wrong colony or tree, thus spurring a war between colonies.

Bill would like to connect each ant colony to a single apple tree so that all n routes are non-intersecting straight lines. In this problem such connection is always possible. Your task is to write a program that finds such connection.

On this picture ant colonies are denoted by empty circles and apple trees are denoted by filled circles. One possible connection is denoted by lines.

Input

The first line of the input file contains a single integer number n (1 ≤ n ≤ 100) — the number of ant colonies and apple trees. It is followed by n lines describing n ant colonies, followed by n lines describing n apple trees. Each ant colony and apple tree is described by a pair of integer coordinates x and y (−10 000 ≤ xy ≤ 10 000) on a Cartesian plane. All ant colonies and apple trees occupy distinct points on a plane. No three points are on the same line.

Output

Write to the output file n lines with one integer number on each line. The number written on i-th line denotes the number (from 1 to n) of the apple tree that is connected to the i-th ant colony.

Sample Input

5
-42 58
44 86
7 28
99 34
-13 -59
-47 -44
86 74
68 -75
-68 60
99 -60

Sample Output

4
2
1
5
3

给你n个蚂蚁的坐标,n个树的坐标,要求每一个蚂蚁连一颗树,连线不能相交。

看到一一匹配,想到二分图。这个图一定可以一一匹配,关键是如何路径不相交。

运用三角形边的性质。

 

AC+BD=AE+ED+BE+EC>AD+BC

所以相交的匹配边权之和一定大于不相交的

只要相交,就一定比不相交大。所以最小权匹配的边一定是不相交的。注意最小权匹配是边不相交的充分条件,而不是必要条件。可以不相交但边权之和大于最小权匹配。

总之,用最小权匹配算出的是最优解,而不是唯一解

至于最小权的求法,就是把边权取相反数,然后求最大权。

一开始竟然用memset给double赋0x3f3f3f3f...果然不行。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
const int N=110;//最大权匹配出来的不是唯一解,是符合情况中一组总路程最小的解 
const double eps=1e-6;
int ant[N][2],tree[N][2],n,con[N];
bool visa[N],visb[N];
double v[N][N],exa[N],exb[N],slack[N];
bool dfs(int a)
{
	visa[a]=1;
	for(int b=1;b<=n;b++)
	{
		if(visb[b])
			continue;
		double gap=exa[a]+exb[b]-v[a][b];
		if(fabs(gap-0)<eps)
		{
			visb[b]=1;
			if(!con[b]||dfs(con[b]))
			{
				con[b]=a;
				return true;
			}
		}
		else
			slack[b]=min(slack[b],gap);
	}
	return false;
}
void km()
{
	mem(con,0);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			slack[j]=30000;
		while(1)
		{
			mem(visa,0);
			mem(visb,0);
			if(dfs(i))
				break;
			double d=INF;
			for(int j=1;j<=n;j++)
				if(!visb[j])
					d=min(d,slack[j]);
			for(int j=1;j<=n;j++)
			{
				if(visa[j])
					exa[j]-=d;
				if(visb[j])
					exb[j]+=d;
				else
					slack[j]-=d;
			}
		}
	}
}
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("in.txt","r",stdin);
	#endif
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)
			scanf("%d%d",&ant[i][0],&ant[i][1]);
		for(int i=1;i<=n;i++)
			scanf("%d%d",&tree[i][0],&tree[i][1]);
		for(int i=1;i<=n;i++) 
		{
			exa[i]=-20000;
			exb[i]=0;
			for(int j=1;j<=n;j++)
			{
				double dis=(ant[i][0]-tree[j][0])*(ant[i][0]-tree[j][0])+(ant[i][1]-tree[j][1])*(ant[i][1]-tree[j][1]);
				v[i][j]=-sqrt(dis);//算边权
				exa[i]=max(v[i][j],exa[i]);
			}
		}
		km();
		int ans[N];
		for(int i=1;i<=n;i++)
			ans[con[i]]=i;
		for(int i=1;i<=n;i++)
			printf("%d\n",ans[i]);
	}
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值