题意:给出蚂蚁和树的坐标,求蚂蚁和树距离最小的匹配
思路:KM算法
错误:最开始用的long long,错了,后来改成double就对了,如果在算距离的时候不开平方也会错,不知道为什么……
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#define CLR(a,b) memset(a,b,sizeof(a));
using namespace std;
const int maxn=105;
typedef long long ll;
struct Point
{
double x;
double y;
};
Point ant[105];
Point tree[105];
double W[105][105];
double Lx[maxn],Ly[maxn];
int leftt[maxn];
bool S[maxn],T[maxn];
int n;
int dcmp(double x)
{
if(abs(x)<=1e-6)return 0;
return x<0?-1:1;
}
bool match(int i)
{
S[i]=true;
for(int j=1;j<=n;++j)
{
if(!T[j]&&dcmp(Lx[i]+Ly[j]-W[i][j])==0)
{
T[j]=true;
if(!leftt[j]||match(leftt[j]))
{
leftt[j]=i;
return true;
}
}
}
return false;
}
void update()
{
double a=2e10;
for(int i=1;i<=n;++i)
{
if(S[i])
{
for(int j=1;j<=n;++j)
{
if(!T[j])
{
a=min(a,W[i][j]-Lx[i]-Ly[j]);
}
}
}
}
for(int i=1;i<=n;++i)
{
if(S[i])Lx[i]+=a;
if(T[i])Ly[i]-=a;
}
}
void KM()
{
for(int i=1;i<=n;++i)
{
leftt[i]=0;
Lx[i]=Ly[i]=0;
}
for(int i=1;i<=n;++i)
{
for(;;)
{
for(int j=1;j<=n;++j)
{
S[j]=T[j]=0;
}
if(match(i))break;
else update();
}
}
}
int main()
{
// freopen("data.txt","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%lf%lf",&tree[i].x,&tree[i].y);
}
for(int i=1;i<=n;++i)
{
scanf("%lf%lf",&ant[i].x,&ant[i].y);
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
W[i][j]=sqrt((ant[i].x-tree[j].x)*(ant[i].x-tree[j].x)+(ant[i].y-tree[j].y)*(ant[i].y-tree[j].y));
// cout<<W[i][j]<<' ';
}
// cout<<endl;
}
KM();
for(int i=1;i<=n;++i)
{
printf("%d\n",leftt[i]);
}
return 0;
}