题解:
二分图最大匹配
根据三角形不等式
直接上最大匹配即可
注意编圈取相反数
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=110;
const double INF=0xffffffffffff,eps=1e-6;
struct Node{double x,y;}Dot1[N],Dot2[N];
double Dist(Node a,Node b)
{
return -sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int n,NX,NY,link[N],visx[N],visy[N];
double Map[N][N],lx[N],ly[N],slack[N];
int FindPath(int u)
{
visx[u]=1;
for (int i=1;i<=NY;i++)
{
if (visy[i])continue;
double temp=lx[u]+ly[i]-Map[u][i];
if (fabs(temp)<=eps)
{
visy[i]=1;
if (link[i]==-1||FindPath(link[i]))
{
link[i]=u;
return 1;
}
}
else if (slack[i]>temp)slack[i]=temp;
}
return 0;
}
void KM()
{
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(link,-1,sizeof(link));
for (int i=1;i<=NX;i++)
for (int j=1;j<=NY;j++)
if (Map[i][j]>lx[i])lx[i]=Map[i][j];
for (int i=1;i<=NX;i++)
{
for (int j=1;j<=NY;j++)slack[j]=INF;
while (1)
{
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
if (FindPath(i))break;
double d=INF;
for (int j=1;j<=NY;j++)
if (!visy[j]&&d>slack[j])d=slack[j];
for (int j=1;j<=NX;j++)
if (visx[j])lx[j]-=d;
for (int j=1;j<=NY;j++)
{
if (visy[j])ly[j]+=d;
else slack[j]-=d;
}
}
}
}
int main()
{
while (~scanf("%d",&n))
{
memset(Map,0,sizeof(Map));
for (int i=1;i<=n;i++)scanf("%lf%lf",&Dot1[i].x,&Dot1[i].y);
for (int i=1;i<=n;i++)scanf("%lf%lf",&Dot2[i].x,&Dot2[i].y);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)Map[i][j]=Dist(Dot1[i],Dot2[j]);
NX=NY=n;
KM();
for (int i=1;i<=N;i++)
for (int j=1;j<=N;j++)
if (link[j]==i)
{
printf("%d\n",j);
break;
}
}
return 0;
}