博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ-3565 Ants---KM算法+slack优化
阅读量:6462 次
发布时间:2019-06-23

本文共 2692 字,大约阅读时间需要 8 分钟。

题目链接:

题目大意:

在坐标系中有N只蚂蚁,N棵苹果树,给你蚂蚁和苹果树的坐标。让每只蚂蚁去一棵苹果树,

一棵苹果树对应一只蚂蚁。这样就有N条直线路线,问:怎样分配,才能使总路程和最小,且

N条线不相交。

解题思路:

用一个图来说明思路。

假设A、B为蚂蚁,C、D为苹果树。则存在两种匹配:第一种是AD、BC,第二种是AC、BD。

根据三角形不等式AD+BC < AC+BD,最后得到很重要的一个性质——满足总路程之和最小

的方案一定不相交。现在来构建二分图,一边为蚂蚁,另一边为苹果树,以距离为边权值,题

目就变为了求带权二分图最小权和的最佳匹配。反向来思考,将距离乘以-1取负值建图,那么

就变为了求带权二分图最大权和的最佳匹配。直接用KM算法来做。

注意:用double,用slack数组优化(比全局变量快很多,网上看到说对于完全图优化会很快,用全局变量代替slack数组就超时)

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 using namespace std; 8 const int maxn = 300 + 10; 9 const int INF = 0x3f3f3f3f; 10 double Map[maxn][maxn]; 11 double wx[maxn], wy[maxn];//顶标值 12 int cx[maxn], cy[maxn]; 13 //cx[i]表示与x部的点i匹配的y部的点的编号 14 //cy[i]表示与y部的点i匹配的x部的点的编号 15 bool visx[maxn], visy[maxn];//标记y部的点是否加入增广路 16 int cntx, cnty;//x部点的数目和y部点的数目 17 double minz;//边权顶标最小值 18 double slack[maxn]; 19 bool dfs(int u)//进入的都是X部的点 20 { 21 visx[u] = 1; 22 for(int v = 1; v <= cnty; v++) 23 { 24 if(!visy[v] && Map[u][v] != INF) 25 { 26 double t = wx[u] + wy[v] - Map[u][v]; 27 if(fabs(t) < 1e-5) 28 { 29 visy[v] = 1; 30 if(cy[v] == -1 || dfs(cy[v])) 31 { 32 cx[u] = v; 33 cy[v] = u; 34 return true; 35 } 36 } 37 else if(slack[v] > t) 38 slack[v] = t; 39 } 40 } 41 return false; 42 } 43 44 void KM() 45 { 46 memset(cx, -1, sizeof(cx)); 47 memset(cy, -1, sizeof(cy)); 48 memset(wy, 0, sizeof(wy)); 49 for(int i = 0; i <= cntx; i++)wx[i] = -1.0 * INF; 50 for(int i = 1; i <= cntx; i++) 51 { 52 for(int j = 1; j <= cnty; j++) 53 { 54 wx[i] = max(wx[i], Map[i][j]); 55 } 56 } 57 for(int i = 1; i <= cntx; i++) 58 { 59 for(int j = 1; j <= cnty; j++) 60 slack[j] = INF; 61 while(1) 62 { 63 minz = 1.0 * INF; 64 memset(visx, 0, sizeof(visx)); 65 memset(visy, 0, sizeof(visy)); 66 if(dfs(i))break; 67 double d = INF; 68 for(int i = 1; i <= cnty; i++) 69 if(!visy[i] && d > slack[i]) 70 d = slack[i]; 71 for(int j = 1; j <= cntx; j++) 72 if(visx[j])wx[j] -= d; 73 for(int j = 1; j <= cnty; j++) 74 if(visy[j])wy[j] += d; 75 else slack[j] -= d; 76 } 77 } 78 for(int i = 1; i <= cntx; i++) 79 printf("%d\n", cx[i]); 80 } 81 struct node 82 { 83 double x, y; 84 }a[maxn], b[maxn]; 85 double dis(node a, node b) 86 { 87 return -sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 88 } 89 int main() 90 { 91 int n; 92 scanf("%d", &n); 93 cntx = cnty = n; 94 for(int i = 1; i <= n; i++)scanf("%lf%lf", &a[i].x, &a[i].y); 95 for(int i = 1; i <= n; i++)scanf("%lf%lf", &b[i].x, &b[i].y); 96 for(int i = 1; i <= n; i++) 97 { 98 for(int j = 1; j <= n; j++) 99 Map[i][j] = dis(a[i], b[j]);100 }101 KM();102 }

 

转载于:https://www.cnblogs.com/fzl194/p/8871516.html

你可能感兴趣的文章
[转]使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(三)-- Logger
查看>>
POJ 3311 Hie with the Pie(状压DP + Floyd)
查看>>
HDU 1402 A * B Problem Plus FFT
查看>>
[CareerCup] 17.3 Factorial Trailing Zeros 求阶乘末尾零的个数
查看>>
Security updates and resources
查看>>
深入理解JavaScript系列(25):设计模式之单例模式
查看>>
DNS为什么通常都会设置为14.114.114.114
查看>>
给定一个序列,判断该序列是否为二叉树查找树的后序遍历序列
查看>>
Sqoop架构(四)
查看>>
golang copy函数
查看>>
《你有多少问题要请示》精华集粹
查看>>
深度 | 机器学习敲门砖:任何人都能看懂的TensorFlow介绍【转】
查看>>
leveldb学习:DBimpl
查看>>
MySQL存储引擎--MYSIAM和INNODB引擎区别
查看>>
[Recompose] Stream Props to React Children with RxJS
查看>>
打印图片
查看>>
apache 配置
查看>>
SHOW CREATE DATABASE Syntax
查看>>
rsync常见问题及解决办法
查看>>
半自动化运维之服务器信息维护
查看>>