POJ-3565 Ants---KM算法+slack优化
题目链接:
https://vjudge.net/problem/POJ-3565
题目大意:
在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标。让每只蚂蚁去一棵苹果树,
一棵苹果树对应一只蚂蚁。这样就有N条直线路线,问:怎样分配,才能使总路程和最小,且
N条线不相交。
解题思路:
用一个图来说明思路。
假设A、B为蚂蚁,C、D为苹果树。则存在两种匹配:第一种是AD、BC,第二种是AC、BD。
根据三角形不等式AD+BC < AC+BD,最后得到很重要的一个性质——满足总路程之和最小
的方案一定不相交。现在来构建二分图,一边为蚂蚁,另一边为苹果树,以距离为边权值,题
目就变为了求带权二分图最小权和的最佳匹配。反向来思考,将距离乘以-1取负值建图,那么
就变为了求带权二分图最大权和的最佳匹配。直接用KM算法来做。
注意:用double,用slack数组优化(比全局变量快很多,网上看到说对于完全图优化会很快,用全局变量代替slack数组就超时)
#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn = + ;
const int INF = 0x3f3f3f3f;
double Map[maxn][maxn];
double wx[maxn], wy[maxn];//顶标值
int cx[maxn], cy[maxn];
//cx[i]表示与x部的点i匹配的y部的点的编号
//cy[i]表示与y部的点i匹配的x部的点的编号
bool visx[maxn], visy[maxn];//标记y部的点是否加入增广路
int cntx, cnty;//x部点的数目和y部点的数目
double minz;//边权顶标最小值
double slack[maxn];
bool dfs(int u)//进入的都是X部的点
{
visx[u] = ;
for(int v = ; v <= cnty; v++)
{
if(!visy[v] && Map[u][v] != INF)
{
double t = wx[u] + wy[v] - Map[u][v];
if(fabs(t) < 1e-)
{
visy[v] = ;
if(cy[v] == - || dfs(cy[v]))
{
cx[u] = v;
cy[v] = u;
return true;
}
}
else if(slack[v] > t)
slack[v] = t;
}
}
return false;
} void KM()
{
memset(cx, -, sizeof(cx));
memset(cy, -, sizeof(cy));
memset(wy, , sizeof(wy));
for(int i = ; i <= cntx; i++)wx[i] = -1.0 * INF;
for(int i = ; i <= cntx; i++)
{
for(int j = ; j <= cnty; j++)
{
wx[i] = max(wx[i], Map[i][j]);
}
}
for(int i = ; i <= cntx; i++)
{
for(int j = ; j <= cnty; j++)
slack[j] = INF;
while()
{
minz = 1.0 * INF;
memset(visx, , sizeof(visx));
memset(visy, , sizeof(visy));
if(dfs(i))break;
double d = INF;
for(int i = ; i <= cnty; i++)
if(!visy[i] && d > slack[i])
d = slack[i];
for(int j = ; j <= cntx; j++)
if(visx[j])wx[j] -= d;
for(int j = ; j <= cnty; j++)
if(visy[j])wy[j] += d;
else slack[j] -= d;
}
}
for(int i = ; i <= cntx; i++)
printf("%d\n", cx[i]);
}
struct node
{
double x, y;
}a[maxn], b[maxn];
double dis(node a, node b)
{
return -sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
int main()
{
int n;
scanf("%d", &n);
cntx = cnty = n;
for(int i = ; i <= n; i++)scanf("%lf%lf", &a[i].x, &a[i].y);
for(int i = ; i <= n; i++)scanf("%lf%lf", &b[i].x, &b[i].y);
for(int i = ; i <= n; i++)
{
for(int j = ; j <= n; j++)
Map[i][j] = dis(a[i], b[j]);
}
KM();
}
POJ-3565 Ants---KM算法+slack优化的更多相关文章
- poj3565 Ants km算法求最小权完美匹配,浮点权值
/** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...
- poj 3565 uva 1411 Ants KM算法求最小权
由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...
- POJ 3565 Ants 【最小权值匹配应用】
传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS Memory Limit: 65536K Total Submissions: ...
- KM算法及其优化的学习笔记&&bzoj2539: [Ctsc2000]丘比特的烦恼
感谢 http://www.cnblogs.com/vongang/archive/2012/04/28/2475731.html 这篇blog里提供了3个链接……基本上很明白地把KM算法是啥讲清楚 ...
- POJ 3565 Ants(最佳完美匹配)
Description Young naturalist Bill studies ants in school. His ants feed on plant-louses that live on ...
- poj 3565 ants
/* poj 3565 递归分治 还有用KM的做法 这里写的分治 按紫书上的方法 不过那里说的有点冗杂了 可以简化一下 首先为啥可以分治 也就是分成子问题解决 只要有一个集合 黑白的个数相等 就一定能 ...
- 【POJ3565】ANTS KM算法
[POJ3565]ANTS 题意:平面上有2*n个点,N白N黑.为每个白点找一个黑点与之连边,最后所有边不交叉.求一种方案. 题解:KM算法真是一个神奇的算法,虽然感觉KM能做的题用费用流都能做~ 本 ...
- poj 2565 Ants (KM+思维)
Ants Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4125 Accepted: 1258 Special Ju ...
- POJ 3565 Ants (最小权匹配)
题意 给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案. 思路 一开始没想到怎么用最小权匹配--后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)--还是 ...
随机推荐
- 简单几步实现 IOS UITextField输入长度的控制
在ios开发过程中,我们有时候需要对UITextField的输入长度进行控制,比如输入手机号码最大长度为11位等,而ios自身又不像android那样可以设置输入框的输入长度,接下来通过简单几步实现这 ...
- 根据T-Code查看用户出口的代码
在此非常非常感谢源作者,这段代码真的非常非常有用好用! REPORT YLBTEST. TABLES : tstc, "SAP Transaction Codes(SAP 事务代 ...
- SSM框架的集成
一 : SpringMVC 接收参数 基本数据类型+String JavaBean 一对一 一对多 Map List 注解 @RequestMapping("/user/add") ...
- 2017ACM/ICPC广西邀请赛
A.A Math Problem #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll ...
- string中执行sql语句
Spring(JdbcTemplate.class)中的queryForMap().queryForObject().queryForLong().queryForInt()等方法都会去调用publi ...
- jdk代理
接口: public interface IUserService { public void saveUser(String username,String password); public vo ...
- SQL Server 脚本跟踪
1.查询 DataBasesID select db_id('regdatas') 2.获取进程ID 3.过滤定位
- Spark Mllib里的分层抽样(使用map作为分层抽样的数据标记)
不多说,直接上干货! 具体,见 Spark Mllib机器学习实战的第4章 Mllib基本数据类型和Mllib数理统计
- sqoop导出hive数据到mysql错误: Caused by: java.lang.RuntimeException: Can't parse input data
Sqoop Export数据到本地数据库时出现错误,命令如下: sqoop export \ --connect 'jdbc:mysql://202.193.60.117/dataweb?useUni ...
- 深入V8引擎-Time核心方法之win篇(2)
这一篇讲windows系统下TimeTicks的实现. 对于tick,V8写了相当长的一段discussion来讨论windows系统上计数的三种实现方法以及各自的优劣,注释在time.cc的572行 ...