题目:http://poj.org/problem?id=3565

首先,我们神奇地发现,没有相交边的匹配可以转化为距离和最小的匹配,所以可以使用KM算法求带权匹配;

要求的是距离和最小,所以把边权转化成负值来求最大;

KM算法有点难理解,看了许多博客,总算朦胧懂了:

首先,每个点有一个“顶标”,用来计算边权和,起初所有左部点的顶标都为相连边的最大边权,右部点的为0;

两个点匹配成功,仅当其顶标和等于其边权(所以可以通过调整顶标来控制边权);

一次dfs没有成功返回0时,我们已经记录下它经过的所有点,这些点都满足“其顶标和等于其边权”条件,组成了一个相等子图;

然而此时的相等子图无法使遍历到的这个左部点得到匹配,所以需要调整顶标;

可知最终的匹配中顶标和等于边权和,为了让顶标和下降最少而又有可能使这个点得到匹配,我们在所有相等子图中的左部点和不在相等子图中的右部点之间找到距离满足条件最小的差值,这样根据它调整顶标后,顶标和下降最少,而又至少会多出这一组可行的点加入相等子图;

这样重复进行,直到这个左部点匹配成功;

最后匹配的权值和是现在的顶标和,这个顶标和比起一开始我们期望的和(每个左部点顶标为其所连最大的边)有所下调,但我们保证每次下调量最少,所以得到最优匹配。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double const inf=999999.999999,eps=1e-;
int const MAXN=;
int n,pre[MAXN],ans[MAXN],xa[MAXN],xb[MAXN],ya[MAXN],yb[MAXN];
double dis[MAXN][MAXN],la[MAXN],lb[MAXN];
bool va[MAXN],vb[MAXN];
bool dfs(int x)
{
va[x]=;
for(int i=;i<=n;i++)
if(!vb[i]&&fabs(la[x]+lb[i]-dis[x][i])<eps)
{
vb[i]=;
if(!pre[i]||dfs(pre[i]))
{pre[i]=x;return ;}
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d%d",&xa[i],&ya[i]);
for(int i=;i<=n;i++)
scanf("%d%d",&xb[i],&yb[i]);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
dis[i][j]=-sqrt(1.0*(xa[i]-xb[j])*(xa[i]-xb[j])+1.0*(ya[i]-yb[j])*(ya[i]-yb[j]));
memset(la,-0x3f,sizeof la);
for(int i=;i<=n;i++)
{
la[i]=dis[i][];
for(int j=;j<=n;j++)
la[i]=max(la[i],dis[i][j]);
}
for(int i=;i<=n;i++)
{
while()
{
memset(va,,sizeof va);
memset(vb,,sizeof vb);
if(dfs(i))break;
double tmp=inf;
for(int i=;i<=n;i++) if(va[i])
for(int j=;j<=n;j++) if(!vb[j])
tmp=min(tmp,la[i]+lb[j]-dis[i][j]);
for(int i=;i<=n;i++)
{
if(va[i])la[i]-=tmp;
if(vb[i])lb[i]+=tmp;
}
}
}
for(int i=;i<=n;i++)
ans[pre[i]]=i;
for(int i=;i<=n;i++)
printf("%d\n",ans[i]);
return ;
}

poj3565Ants——KM算法的更多相关文章

  1. 匈牙利算法与KM算法

    匈牙利算法 var i,j,k,l,n,m,v,mm,ans:longint; a:..,..]of longint; p,f:..]of longint; function xyl(x,y:long ...

  2. 【HDU2255】奔小康赚大钱-KM算法

    Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description ...

  3. HDU2255-奔小康赚大钱-二分图最大权值匹配-KM算法

    二分图最大权值匹配问题.用KM算法. 最小权值的时候把权值设置成相反数 /*-------------------------------------------------------------- ...

  4. KM算法及其优化的学习笔记&&bzoj2539: [Ctsc2000]丘比特的烦恼

    感谢  http://www.cnblogs.com/vongang/archive/2012/04/28/2475731.html 这篇blog里提供了3个链接……基本上很明白地把KM算法是啥讲清楚 ...

  5. poj 2195 KM算法

    题目链接:http://poj.org/problem?id=2195 KM算法模板~ 代码如下: #include "stdio.h" #include "string ...

  6. hdu 2255 奔小康赚大钱--KM算法模板

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 题意:有N个人跟N个房子,每个人跟房子都有一定的距离,现在要让这N个人全部回到N个房子里面去,要 ...

  7. HDU(2255),KM算法,最大权匹配

    题目链接 奔小康赚大钱 Time Limit: 1000/1000MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  8. 二分图 最大权匹配 km算法

    这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...

  9. hdu 2255 奔小康赚大钱 KM算法

    看到这么奇葩的题目名我笑了,后来这么一个裸的KM调了2小时我哭了…… 这是个裸的KM算法,也没什么多说的,主要是注意多组数据时,每次都要把各种数组清空啊,赋值啊什么的,反正比较麻烦.至于为什么调了2小 ...

随机推荐

  1. C#串口通信发送数据

    1 发送数据 需要2个串口 http://www.openedv.com/thread-228847-1-1.html 下载源文件 File_Protocol_Test.rar

  2. Majority Number

    题目描写叙述 链接地址 解法 算法解释 题目描写叙述 Given an array of integers, the majority number is the number that occurs ...

  3. python入门之搭建环境

    进入以下网站:python.org 选择你喜欢(需要)的版本下载 点击下载即可,本次提供下载:python3.6.3 (国外架设,非常慢) ,用百度的平台吧:python3.6.1,多谢百度. 开始安 ...

  4. 无法安装 golang.org/x/tools/的库

    安装godep 官方的安装文档是使用go get github.com/tools/godep,很可惜,因为“网络”问题会报一个找不到golang.org/x/tools/go/vcs的错误. 而ht ...

  5. 怎样把多个Android Project打包成一个APK

    怎样把多个Android Project打包成一个APK(你的项目怎样引用其它项目). 怎样把多个android project 打包成一个apk呢,事实上原理是这种.一个主project引用其它的p ...

  6. servelet

    获取页面传递过来的参数. 调用后台代码实现相关业务逻辑. 根据返回结果,进行页面跳转.   问题:httpsession? 拆解: String 里面的.spllit方法.拆开后,返回值为string ...

  7. Codeforces 569 B. Inventory

    click here~~ **B. Inventory** time limit per test1 second memory limit per test256 megabytes inputst ...

  8. vim 寄存器的使用

    1. 寄存器的格式 "[a~z] 2. 在复制时指定寄存器:"ayw 3. 剪切时使用寄存器:"add 3. 黏贴时指定从某个寄存器处获取数据:"ap 4. 几 ...

  9. remote connect openshift mysql

    再虚拟机内 rhc port-forward <app-name> 此时,可以在本机 访问 127.0.0.1:8080  登陆 网页, 3306连接sql https://unix.st ...

  10. mysql 较为高效的分页

    直接上代码 DaoImpl: /** * 开发转让页面展示 ,查询搜索数据,而且分页展示 * @param zrdp 搜索条件封装对象 * @return */ @SuppressWarnings(& ...