题目链接:

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优化的更多相关文章

  1. poj3565 Ants km算法求最小权完美匹配,浮点权值

    /** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...

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

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

  3. POJ 3565 Ants 【最小权值匹配应用】

    传送门:http://poj.org/problem?id=3565 Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: ...

  4. KM算法及其优化的学习笔记&&bzoj2539: [Ctsc2000]丘比特的烦恼

    感谢  http://www.cnblogs.com/vongang/archive/2012/04/28/2475731.html 这篇blog里提供了3个链接……基本上很明白地把KM算法是啥讲清楚 ...

  5. POJ 3565 Ants(最佳完美匹配)

    Description Young naturalist Bill studies ants in school. His ants feed on plant-louses that live on ...

  6. poj 3565 ants

    /* poj 3565 递归分治 还有用KM的做法 这里写的分治 按紫书上的方法 不过那里说的有点冗杂了 可以简化一下 首先为啥可以分治 也就是分成子问题解决 只要有一个集合 黑白的个数相等 就一定能 ...

  7. 【POJ3565】ANTS KM算法

    [POJ3565]ANTS 题意:平面上有2*n个点,N白N黑.为每个白点找一个黑点与之连边,最后所有边不交叉.求一种方案. 题解:KM算法真是一个神奇的算法,虽然感觉KM能做的题用费用流都能做~ 本 ...

  8. poj 2565 Ants (KM+思维)

    Ants Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4125   Accepted: 1258   Special Ju ...

  9. POJ 3565 Ants (最小权匹配)

    题意 给出一些蚂蚁的点,给出一些树的点,两两对应,使他们的连线不相交,输出一种方案. 思路 一开始没想到怎么用最小权匹配--后来发现是因为最小权匹配的方案一定不相交(三角形两边之和大于第三边)--还是 ...

随机推荐

  1. Python爬虫开发

    1. 语法入门 Python教程 2. 爬虫学习系列教程 1)宁哥的小站 https://github.com/lining0806/PythonSpiderNotes 2)Python爬虫开发 3) ...

  2. 让你的spring-boot应用日志随心所欲--spring boot日志深入分析

    1.spring boot日志概述 spring boot使用Commons Logging作为内部的日志系统,并且给Java Util Logging,Log4J2以及Logback都提供了默认的配 ...

  3. Spring-【高阶】注解-转载

    从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,某些场合可以取代 ...

  4. EOS概念理解总结

    本文参考EOS版本:v1.1.1 一.EOS投票相关 //用户投票1.不能自己代理自己,但可以自己给自己投票; 2.投票的生产节点名称不能重复;3.投票人设置了投票代理人后自己不能再投票;4.投票人需 ...

  5. Jmeter分布式(转)jmeter -n -t baidu.jmx -l result.jtl -R 172.16.20.146:1099

    1.准备2台在同一个局域网内的机器,一台作为master主控机,一台作为slave 执行机 master机器ip:172.16.20.134 slave机器ip:172.16.20.146 2.在2台 ...

  6. poi使用

    1.首先需要下载Apache POI 打开poi下载的链接:http://poi.apache.org/download.html  ,点击“The latest stable release is ...

  7. (jmeter内置可调用的变量)jmeter beanShell断言

    用户可以在jmeter- “beanShell断言”中自定义断言.自由灵活的用脚本实现自己的断言  beanShell断言接口介绍  在beanShell中直接可以调用的变量,无需加前缀.  1.lo ...

  8. 为什么要问Servlet的初始化时间

    Servlet的init方法到底是在什么时候调用的? j2ee specification和java doc中有以下说明 如果load-on-startup设置为>=0, 部署的时候就会调用.  ...

  9. jsonp——使用公共接口获取数据

    demo: <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8 ...

  10. mediawiki登录时第一次会跳回登录页面,第二次才能登录成功

    原因是:LocalSetting.php中的$wgServer属性使用的是ip,改为域名后成功解决问题 补充:改为域名后使用ip访问会出现第一次登录跳回登录界面的情况,应该根据实际情况来设置$wgSe ...