题意:

一个平面上有n个黑色的点,n个白色的点,要求黑色的点与白色点之间一一配对,且线段之间不相交。

思路:

线段不相交并不好处理,想了很久想不出,所以看了蓝书的讲解。

一个很明显的结论是,不相交的线段一定比相交的线段短,如图:一个较为直观的例子。

由于点之间一一对应,所以肯定用二分图匹配,然后要使得所有线段之和最短,那么就是求一个带权最小匹配,上KM算法解决。

把所有的边权取负值,求最大匹配即可。

代码:

 #include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int N = ; double mp[N][N]; struct node
{
double x,y;
node(double a,double b)
{
x = a;
y = b;
}
}; vector<node> nx,ny; bool vis_x[N],vis_y[N];
int match[N];
double lx[N],ly[N];
double slack[N];
int ma[N]; double cal(int i,int j)
{
double dx = pow(nx[i].x - ny[j].x,);
double dy = pow(nx[i].y - ny[j].y,); return sqrt(dx + dy);
} bool dfs(int u,int n)
{
vis_x[u] = ; for (int i = ;i < n;i++)
{
if (vis_y[i]) continue; double gap = lx[u] + ly[i] - mp[u][i]; //getchar(); //printf("%.6f %.6f %.6f %.6f\n",lx[u],ly[i],mp[u][i],gap); if (fabs(gap) < 1e-)
{
vis_y[i] = ; if (match[i] == - || dfs(match[i],n))
{
match[i] = u;
return true;
}
}
else
{
slack[i] = min(slack[i],gap);
}
} return false;
} void km(int n)
{
memset(ly,,sizeof(ly));
memset(match,-,sizeof(match)); for (int i = ;i < n;i++)
{
lx[i] = mp[i][]; for (int j = ;j < n;j++)
{
lx[i] = max(lx[i],mp[i][j]);
}
} for (int i = ;i < n;i++)
{
for (int j = ;j < n;j++) slack[j] = 1e15;
//printf("gg");
while ()
{
//printf("233");
memset(vis_x,,sizeof(vis_x));
memset(vis_y,,sizeof(vis_y)); if (dfs(i,n)) break; double d = 1e15; for (int j = ;j < n;j++)
{
if (!vis_y[j]) d = min(slack[j],d);
} for (int j = ;j < n;j++)
{
if (vis_x[j]) lx[j] -= d; if (vis_y[j]) ly[j] += d;
} //getchar(); //printf("%.6f **\n",d);
}
}
} int main()
{
int n;
int kase = ; while (scanf("%d",&n) != EOF)
{
if (kase++) printf("\n"); nx.clear();
ny.clear(); for (int i = ;i < n;i++)
{
double x,y;
scanf("%lf%lf",&x,&y); nx.push_back(node(x,y));
} for (int i = ;i < n;i++)
{
double x,y;
scanf("%lf%lf",&x,&y); ny.push_back(node(x,y));
} for (int i = ;i < n;i++)
{
for (int j = ;j < n;j++)
{
mp[i][j] = -cal(i,j);
}
} km(n); for (int i = ;i < n;i++)
{
int a = i + ,b = match[i] + ;
ma[b] = a;
} for (int i = ;i < n;i++)
{
printf("%d\n",ma[i+]);
}
} return ;
}

uva 1411 Ants的更多相关文章

  1. UVA 1411 - Ants(二分图完美匹配)

    UVA 1411 - Ants 题目链接 题意:给定一些黑点白点,要求一个黑点连接一个白点,而且全部线段都不相交 思路:二分图完美匹配,权值存负的欧几里得距离,这种话,相交肯定比不相交权值小,所以做一 ...

  2. uva 1411 Ants (权值和最小的完美匹配---KM算法)

    uva 1411 Ants Description Young naturalist Bill studies ants in school. His ants feed on plant-louse ...

  3. poj 3565 uva 1411 Ants KM算法求最小权

    由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...

  4. 【uva 1411 Ants蚂蚁们】

    题目大意: ·给你一个n,表示输入n个白点和n个黑点(输入每一个点的坐标).现在需要将各个白点和各个黑点一一用线段连接起来,需要满足这些线段不能够相交. ·特色: 我们如何保证线段间不相交. ·分析: ...

  5. UVa 1411 Ants(分治)

    https://vjudge.net/problem/UVA-1411 题意:n只蚂蚁和n颗苹果树,一一配对并且不能交叉. 思路:这就是巨人与鬼的问题.用分治法就行了. #include<ios ...

  6. 【UVA 1411】 Ants (KM)

    Young naturalist Bill studies ants in school. His ants feed onplant-louses that live on apple trees. ...

  7. UVA 10714 Ants 蚂蚁 贪心+模拟 水题

    题意:蚂蚁在木棍上爬,速度1cm/s,给出木棍长度和每只蚂蚁的位置,问蚂蚁全部下木棍的最长时间和最短时间. 模拟一下,发现其实灰常水的贪心... 不能直接求最大和最小的= =.只要求出每只蚂蚁都走长路 ...

  8. Ants UVA - 1411(km板题竟然让我换了个板子)

    题意: 给出n个白点和n个黑点的坐标,要求用n条不相交的线段把它们连接起来,其中每条线段恰好连接一个白点和一个黑点,每个点恰好连接到一条线段 解析: 带入负的欧几里得距离求就好了 假设a1-b1 与 ...

  9. uva 10714 Ants(贪心)

    题目连接:10714 - Ants 题目大意:一根棍子上有n只蚂蚁, 这些蚂蚁开始可以任意朝着一个方向移动一直走,向左或是向右,并且移动速度是相同的,但是一旦蚂蚁碰到迎面走来的另一只蚂蚁,那么这两只蚂 ...

随机推荐

  1. pxe自动化批量安装系统(Centos7)

    PXE:preboot execute environment 环境实现:主服务器ip:10.0.10.1 1 tfpt trivial简单文件共享服务,基于udp协议工作: 加载系统安装程序: 69 ...

  2. 什么是DOM,DOM level 1\2\3 的区别是什么

    DOM 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标志语言的标准编程接口.Document Object Model的历史可以追溯至1990年 ...

  3. Docker(四):Docker 三剑客之 Docker Compose

    前两篇文章我们介绍了 Dockerfile 的使用Docker(二):Dockerfile 使用介绍,我们知道使用一个 Dockerfile 模板文件可以定义一个单独的应用容器,如果需要定义多个容器就 ...

  4. 巧用linux版powershell,管理linux下的docker

    大家好,我把用powershell的docker马甲命令的好处,放在了页面下方,从第五章开始. powershell 传教士 原创文章 始于 2017-09-07 允许转载,但必须保留名字和出处,否则 ...

  5. linux No space left on device 由索引节点(inode)爆满引发500问题

    inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统读取 ...

  6. C#之字符串

    1 Replace string sayHello = "Hello World!"; Console.WriteLine(sayHello); sayHello = sayHel ...

  7. 转载--MYSQL5.7:Access denied for user 'root'@'localhost' (using password:YES)解决方法

    1.打开MySQL目录下的my.ini文件,在文件的最后添加一行"skip-grant-tables",保存并关闭文件; 2.重启MySQL服务; 3.通过cmd行进入MySQL的 ...

  8. Flume日志采集系统

    1.简介 Flume是Cloudera提供的一个高可用.高可靠.分布式的海量日志采集.聚合和传输的系统. Flume支持在日志系统中定制各类数据发送方用于收集数据,同时Flume提供对数据进行简单的处 ...

  9. Spring学习笔记四 整合SSH

    三大框架架构(整合原理) 步骤1:导包 Hibernate包 1.Hibernate包,hibernate/lib/required 2.hibernate/lib/jpa | java persis ...

  10. Java基础学习笔记一 Java介绍

    java语言概述 Java是sun公司开发的一门编程语言,目前被Oracle公司收购,编程语言就是用来编写软件的. Java的应用 开发QQ.迅雷程序(桌面应用软件) 淘宝.京东(互联网应用软件) 安 ...