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]);
	}
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章