题意:给出N个白点和N个黑点,要求用N条不相交的线段把它们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接到一条线段。

分析:因为有结点黑白两色,我们不难想到构造一个二分图,其中每个白点对应一个X结点,每个黑点对应一个Y结点,每个黑点和每个白点相连,权值等于二者的欧几里德距离。建模后最佳完美匹配就是问题的解。为什么呢?假设在最佳完美匹配中有两条线段a1-b1与a2-b2相交,那么dist(a1,b1)+dist(a2,b2)一定大于dist(a1,b2)+dist(a2,b1),因此如果把这两条改成a1-b2和a2-b1后总长度会变少,与最佳二字矛盾。

注意:KM算法是求权值和最大的,故需要将距离边成负数即可。并且输入坐标值好像是浮点的。

参考自:http://www.cnblogs.com/arbitrary/archive/2013/02/27/2936008.html

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define Del(x,y) memset(x,y,sizeof(x))
#define N 105
#define INF 999999999
struct Point
{
double x,y;
} point[N*]; double dis(Point a,Point b)
{
return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
} double lx[N],ly[N]; //顶点标号
int link[N];       //存放与T点集连结的S点集里的点
int S[N],T[N]; //visit,是否属于相等子图
double w[N][N];
int n; bool match(int i) //匈牙利
{
S[i]=true;
for(int j=;j<=n;j++)
{
if(abs(lx[i]+ly[j]-w[i][j])<10e-&&!T[j])
{
T[j]=true;
if(link[j]==||match(link[j]))
{
link[j]=i;
return true;
}
}
}
return false;
} void update() //更新顶点标号
{
double a=INF;
for(int i=;i<=n;i++)
if(S[i])
for(int j=;j<=n;j++)
if(!T[j])
a=min(a,lx[i]+ly[j]-w[i][j]);
for(int i=;i<=n;i++)
{
if(S[i]) lx[i]-=a; //S集里的点-a
if(T[i]) ly[i]+=a; //T集里的点+a
}              //其余所有点不变
} void KM()
{
for(int i=; i<=n; i++)
{
link[i]=lx[i]=ly[i]=;
for(int j=; j<=n; j++)
lx[i]=max(lx[i],w[i][j]);
}
for(int i=; i<=n; i++)
for(;;)
{
Del(S,);
Del(T,);
if(match(i))break;
else update();
}
} int ans[N]; int main()
{
scanf("%d",&n);
for(int i=; i<=n*; i++)
scanf("%lf%lf",&point[i].x,&point[i].y);
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
w[i][j]=-dis(point[i],point[j+n]);
KM();
for(int i=;i<=n;i++)
ans[link[i]]=i;
for(int i=;i<=n;i++)
printf("%d\n",ans[i]);
return ;
}

POJ_3565_Ants的更多相关文章

随机推荐

  1. 码农小汪-spring框架学习之2-spring IoC and Beans 控制反转 依赖注入 ApplicationContext BeanFactory

    spring Ioc依赖注入控制反转 事实上这个东西很好理解的,并非那么的复杂. 当某个Java对象,须要调用还有一个Java对象的时候(被依赖的对象)的方法时.曾经我们的做法是怎么做呢?主动的去创建 ...

  2. 我和nupt集训队的故事

    纯水文,如有不适请ctrl+w撤离 亚洲赛刚结束.看了不少巨巨的退役贴以及岛娘在知乎上的那篇感天动地的人生经历.多少有点夜深忽梦少年事的错觉.作为一个两年前就打出gg的高龄选手,之后又强行以1次队员和 ...

  3. Linux下Gcc 的编译过程

    在linux下开发难免会用到gcc编译.GCC(GNU Compiler Collection.GNU编译器套装),是由 GNU 开发的编程语言编译器.它是GNU编译器套装以GPL许可证所发行的自由软 ...

  4. Zend Studio如何调试?

    1.安装Zend Studio之前,本机已安装Apache2.如果使用Apache2作为服务器 Window-Preferences-Php-Php Servers 配置好 URL和Server Ro ...

  5. go4--break,continue + 标签

    package main /* 指针 Go虽然保留了指针,但与其它编程语言不同的是,在Go当中不 支持指针运算以及”->”运算符,而直接采用”.”选择符来操作指针 目标对象的成员 操作符”&am ...

  6. javaSE基础(三)

    泛型类:像ArrayList这样的特殊类,他们允许通过类型参数来指明使用的数据类型. 报装类:一种用于将基本类型的数据"封装"成对象的类. 装箱:将 基本类型的数据自动转换为对应类 ...

  7. bzoj4868

    http://www.lydsy.com/JudgeOnline/problem.php?id=4868 三分+贪心 我们可以知道这是一个单峰函数 当A>B那么我们每次调整一个的价钱是最佳的,所 ...

  8. 让你彻底明白JAVA中堆与栈的区别

    原文地址:http://www.2cto.com/kf/201302/190704.html 简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象 ...

  9. sshd服务器搭建管理和防止暴力破解

    1.1 Linux服务前期环境准备,搭建一个RHEL7环境 1.2 sshd服务安装-ssh命令使用方法 1.3 sshd服务配置和管理 1.4 防止SSHD服务暴力破解的几种方式 1.1 Linux ...

  10. python自动化测试学习笔记-9测试框架

    学习了这么久的python,我们已经可以自己搭建一个简单的测试和框架了,先从简单的开始,有时我们编写接口的测试用例会用excel进行编写,以下面的接口测试用例模板为例,进行编写: