题解:
二分图最大匹配
根据三角形不等式
直接上最大匹配即可
注意编圈取相反数
代码:
#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 ",j); break; } } return 0; }