题意:给出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. jqury-validate表单验证

    首先需要引入插件:jquery.validate.js这个插件. 然后对需要验证的表单实现js: $("#add-firewalls-form").validate({ submi ...

  2. C Language Study - gets , getchar &amp; scanf

    慢慢的发现C语言功底是如此的薄弱,被这几个字符输入函数搞糊涂了又~~ 来,再来忧伤一次吧~ 那么.我们从scanf開始: 假如说你要将一串字符输入到一字符数组里,例如以下面程序, char a[2]; ...

  3. MySQL测试代码

    MySQL测试代码 # 注释内容 -- 注释内容 -- 创建maizi数据库 CREATE DATABASE IF NOT EXISTS `maizi` DEFAULT CHARACTER SET ' ...

  4. Hibernate- Criteria 简易

    package cn.demo; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; ...

  5. 【Dairy】2016.11.5

    橘子洲一游

  6. 基于ASP.NET MVC的快速开发平台,给你的开发一个加速度!

    基于ASP.NET MVC的快速开发平台,给你的开发一个加速度! bingo炸了 2017/4/6 11:07:21 阅读(37) 评论(0) 现在的人做事情都讲究效率,最好能达到事半功倍那种效果,软 ...

  7. android 制作9.png图片

    什么叫.9.PNG呢,这是安卓开发里面的一种特殊的图片   这种格式的图片在android 环境下具有自适应调节大小的能力.   (1)允许开发人员定义可扩展区域,当需要延伸图片以填充比图片本身更大区 ...

  8. Python实现用户交互,显示省市县三级联动的选择

    题目:Python实现用户交互,显示省市县三级联动的选择 定义的字典为: dic = { "江西": { "萍乡": ["安源", &quo ...

  9. linux线程相关函数接口

    以下内容转自网络 索引:1.创建线程pthread_create2.等待线程结束pthread_join3.分离线程pthread_detach4.创建线程键pthread_key_create5.删 ...

  10. Eclipse中直接执行sql语句(图文说明)

    转自:https://blog.csdn.net/changjyzzu/article/details/45487847 1.首先新建sql文件,然后打开文件 22.右键点击空白处,点击set-con ...