题目: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. Linux 主机被入侵后的处理案例

    Linux主机被入侵后的处理案例 提交 我的留言 加载中 已留言 一次Linux被入侵后的分析 下面通过一个案例介绍下当一个服务器被rootkit入侵后的处理思路和处理过程,rootkit攻击是Lin ...

  2. Git以及github的使用方法(一)安装并设置git用户

    最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Window ...

  3. require.js使用

    无可奈何,二开项目用了require.js! 一道槛是挨不过去了 require官网: http://requirejs.org/ require.js cdn: <script src=&qu ...

  4. Eclipse 视图

    Eclipse 视图 关于视图 Eclipse视图允许用户以图表形式更直观的查看项目的元数据. 例如,项目导航视图中显示的文件夹和文件图形表示在另外一个编辑窗口中相关的项目和属性视图. Eclipse ...

  5. 梦入IBM之java基础-网络编程

    如今我们来谈谈最后的内容:网络编程: 1):TCP中是线程与线程进行通讯!内部的执行机制是这种:先有一个线程去监听某个port.然后假设有Socket连接上来了以后,server会生成一个Socket ...

  6. java性能监控工具jps-windows

    jps Lists the instrumented Java Virtual Machines (JVMs) on the target system. This command is experi ...

  7. 用 Sencha Touch 构建移动 web 应用程序

    Sencha Touch 是一个使用 HTML5.CSS3 和 JavaScript 语言构建的移动 web 应用程序框架,在本文中,学习如何应用您当前的 web 开发技能进行移动 web 开发.下载 ...

  8. windown vs2012 编译ffplay

    自己写的播放器播放有些文件出现问题,但ffplay播放都很正常,为方便调试,将ffplay.c编译成可执行文件. 一. 环境搭建 环境搭建前面已经有文章介绍,没有特殊的地方,不再赘述. 二.修改con ...

  9. 实现iOS7上tableView的切割线像iOS6中的效果

    iOS7上tableView的切割线左边短了一点,要实现和iOS6中的效果还是有方法的,UITableView头文件中个属性: @property (nonatomic)         UIEdge ...

  10. 横向卷轴(side-scrolling)地图的canvas实现

    标题有点小题大作了,实际上是实现一张看起来连续的运动背景图片. 效果如下:   // 实现原理: 图片1与图片2是两张首尾衔接的图片,图片1以一定速度移出canvas,图片2慢慢移进canvas,当图 ...