题解:

二分图最大匹配

根据三角形不等式

直接上最大匹配即可

注意编圈取相反数

代码:

#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;  
}  

  

posted on 2018-01-18 18:05  宣毅鸣  阅读(90)  评论(0编辑  收藏  举报