hrbust 1680 连线
给出n白点和n个黑点的坐标,要求用n条不相交的线段把他们连接起来,其中每条线线段恰好
连接一个白点和一个黑点,每个点恰好连接到一条线段。
输出对应的所有方案中
n条不相交线段总长度最短的长度
#include<stdio.h>
#include<string.h>
#include<math.h>
#define INF 0x1f1f1f1f
#define clr(x)memset(x,0,sizeof(x))
int sx[202],sy[202];
double lx[202],ly[202];
int link[202];
double map[202][202];
int n;
int find(int x)
{
sx[x]=1;
int i;
for(i=1;i<=n;i++)
if(!sy[i]&&lx[x]+ly[i]-map[x][i]<0.00000000001)
{
sy[i]=1;
if(link[i]==0||find(link[i]))
{
link[i]=x;
return 1;
}
}
return 0;
}
double KM()
{
int i,j,v;
double sum,dmin;
for(i=1;i<=n;i++)
{
lx[i]=-INF;
ly[i]=0;
for(j=1;j<=n;j++)
if(map[i][j]>lx[i])
lx[i]=map[i][j];
}
clr(link);
for(v=1;v<=n;v++)
while(1)
{
clr(sx); clr(sy);
if(find(v)) break;
dmin=INF;
for(i=1;i<=n;i++)
if(sx[i])
for(j=1;j<=n;j++)
if(!sy[j]&&lx[i]+ly[j]-map[i][j]<dmin)
dmin=lx[i]+ly[j]-map[i][j];
for(i=1;i<=n;i++)
{
if(sx[i])
lx[i]-=dmin;
if(sy[i])
ly[i]+=dmin;
}
}
sum=0;
for(i=1;i<=n;i++)
sum+=map[link[i]][i];
return sum;
}
double a[200][2];
double b[200][2];
int main()
{
int i,j,t,m;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
memset(map,-INF,sizeof(map));
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&a[i][0],&a[i][1]);
}
for(i=1;i<=n;i++)
{
scanf("%lf%lf",&b[i][0],&b[i][1]);
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
map[i][j]=-sqrt((a[i][0]-b[j][0])*(a[i][0]-b[j][0])+(a[i][1]-b[j][1])*(a[i][1]-b[j][1]));
}
printf("%.4lf\n",-KM());
}
return 0;
}