题目: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 ;
}

最新文章

  1. 如何安装ipa文件
  2. 用Groovy构建java脚本
  3. pch头文件
  4. Python中用datetime包进行对时间的一些操作
  5. Python十分钟学会
  6. ios开发——实用技术总结Swift篇&amp;swift常用开发技术总结
  7. Java 调用Dll
  8. python GUI学习——Tkinter
  9. UIAlertController高级之嵌入其他控件
  10. Hive基础(4)---Hive的内置服务
  11. pymysql 多字段插入
  12. MongoDB与Spring整合(支持事务)——SpringDataMongoDB
  13. 用 gdb 调试 GCC 程序
  14. Hadoop基础--统计商家id的标签数案例分析
  15. checklistbox的用法
  16. 简单的Java,Python,C,C++
  17. 使用 Headless Chrome 进行页面渲染 - 知乎专栏
  18. mysql InnoDB 的行锁
  19. Hibernate 之单向多对一映射及其衍生问题
  20. Java泛型拾遗

热门文章

  1. Highcharts常用的最核心的参数选项配置详细说明
  2. Java菜鸟到大牛学习路线培训教程
  3. 猫猫学iOS之小知识之_xcode插件的删除方法_自己主动提示图片插件KSImageNamed有时不灵_分类或宏之类不能自己主动提示,
  4. go mysql dsn
  5. c#列表操作
  6. 显卡接口PCI、VGA、PCIE
  7. mysql 找出外键等约束
  8. POJ 3335 Rotating Scoreboard(半平面交 多边形是否有核 模板)
  9. 下载与安装---tensorflow on linux
  10. java线程中断[interrupt()函数] (转载)