问题描述

平面上有n个不重合的点,你的任务是求这些点的最小生成树。两个点(x0,y0)和(x1,y1)之间的距离定义为|x0-x1|+|y0-y1|。(即曼哈顿距离)

如果在任意两个点之间都连一条边,边的权值等于两点的曼哈顿距离,那么这个题目就是标准的最小生成树问题。一个包含n个点n2条边的图,求最小生成树的代价是O(n2)。但是这种一般性的做法没有

考虑到“平面”的性质。下面将通过分析最小生成树的性质和平面性质的结合,得到一个O(nlogn)的算法。

最小生成树的“环切”性质

先抛开“平面”,我们考虑一般的离散图的最小生成树有什么性质。

环切性质 在图G=(V,E)中,如果存在一个环,把环中权最大的边e删除得到图G’=(V,E/{e})(如果有多条最大边,则删除任意一条),则G和G’的最小生成树权和相同。

证明:

假设e(e∈E)在G的一个环C上,并且是环上的权最大边。

假设G的某棵最小生成树T包含了e,考虑e连接的两个点u和v。把e从T中删除,就把T分成两个连通分量,u,v分处不同的连通分量。在环C上对应的把e删除,从u到v还是有一条通路,并且通路上的所有边

权值都不大于e的权值;假设这条通路是(u, x1, x2, …, xL, v)。

在点集S={u, x1, x2, …, xL, v}中,和u属于同一个集合的点称之为红点,和v属于同一个集合的称之为蓝点。显然S中至少有一个红点(u)、至少有一个蓝点(v)。所以在序列(u, x1, x2, …, xL, v)中

必然存在相邻的两个点颜色不同,不妨设为a和b。将<a,b>加入到被删除了e的T中,就得到了一棵新的生成树T’:即T’=(T/{e})∪{<a,b>}。前面提到了通路(u, x1, x2, …, xL, v)中任意一条边都不

大于e,所以<a,b>的权不大于e的权。即T’也是G的一棵最小生成树。

因为G’是G的子图,所以T’也是G’的最小生成树。而T和T’的权和相等(都是G的最小生成树)。

证毕。

区域分类法

通过最小生成树的“环切”性质,我们可以发现有很多边是没有用的。如果图中存在一个环,那么就至少能删掉一条边而保持最小生成树不变。

我们回到“平面”问题。基本思路还是构建一个离散图——但是这个图的边数必须远远小于n2。换句话说我们要想办法利用“环切”性质,只保留一些有用的边。

考察某个点s。我们从s发出8条射线将平面均分成八个部分,

如果点落在射线上,按如下方法划分:

实线上的点属于这个区域、虚线上的点不属于。上图中p, q都属于该区域。

下面我们证明:在每个区域里面,s只要和至多一个点连边即可。

八个扇形区域是对称的,我们只考虑R1。

把s看作原点,R1里面的点(x,y)都满足:

x≥0,

y>x.

考察R1里面两个点p和q,不失一般性设xp≤xq。

1.       yp≤yq

|PQ|=xq+yq-(xp+xq)

|SP|=xp+yp

|SQ|=xq+yq

所以|PQ|=|SQ|-|SP|≤|SQ|

可见当yp≤yq时,|PQ|不是三角形SPQ的最长边。(在曼哈顿距离下的“最长”)

2.       yp>yq-

0≤xp≤xq≤yq<yp

|PQ|=xq-xp+yp-yq

|SP|=xp+yp

|SQ|=xq+yq

即|PQ|= (yp-xp)+(xq-yq)

因为xq≤yq,所以|PQ|≤yp-xp≤yp≤xp+yp=|SP|

也就是说,当yp>yq时,|PQ|仍然不是三角形SPQ的最长边。(曼哈顿距离意义下的“最长”)

综上,|PQ|无论如何也不可能是三角形SPQ的最长边。即:在环<s, p, q>中,最大边只可能是|SP|和|SQ|。根据“环切”性质,我们把|SP|和|SQ|中的较长边删除即可。

假设R1里面有m个顶点:P1, P2, …, Pm,假设距离s最近的点是Pk,那么只要在S和Pk之间连边即可。

所谓距离s最近的点,实际上就是xk+yk最小的点。

图的构建方法

按照上一节介绍的方法,我们可以构建出一个至多含有8n条边的图。可是如何构造呢?如果对于每个点s,把所有的点都判断一次取最小值,那么复杂度是O(n2),没有任何意义。下面我们考虑设计一个

高效的算法,实现“找到每个点的R1区域内,离其最近的点”的操作。

找s的R1区域内离s最近的点,实际上就是找s的R1区域内x+y最小的点。

我们把所有的点按照x从小到大排序:x1≤x2≤…≤xn。

建立一个抽象数据结构T。T中的每个元素对应平面上的一个点(x,y),该元素的第一关键字等于y-x,第二关键字等于y+x。

从Pn到P1逐个处理每个点。处理Pk的时候,令Pk+1, Pk+2, …, Pn都已经存入到T中。某个点Q(x,y)如果落在Pk的R1区间内,必须满足:

1.       x≥xk

2.       y-x>yk-xk

要满足第一个条件,Q必须属于集合{Pk+1, Pk+2, …, Pn},即Q必然在T中。

要满足第二个条件,Q在T中的第一关键字必须大于yk-xk(定值)。

因为我们要使得|PkQ|最小,所以我们实际上就是:从T的第一关键字大于某常数的所有元素中,寻找第二关键字最小的元素。

很明显,T可以用线段树来实现。按照第一关键字有序来建立线段树,对于线段树每个节点都记录以其为根的子树中第二关键字最小的是哪个元素。查询、插入的时间复杂度都是O(logn)。

线段树也可以用平衡二叉树代替。

对于Pk,找到符合上述条件并使|PkQ|最小的Q之后,在Pk和Q之间连一条边,并将Pk插入T;继续处理Pk-1(除非k=1)。

经过上面的处理,我们就把每个点在R1区域内的最近点求出来了。同样的处理R2, R3, …, R8即可把整个离散图构建出来。

一点优化

如果把R1, R2, …, R8分别处理,则整个算法的复杂度系数过大。

我们很容易注意到,R1和R5是对称的,只要处理其中一个区域即可。根据对称性,我们只要处理R1, R2, R3, R4这四个区域。

如果点(x,y)在Ps的R1区域内,则:

1.       x≥xk

2.       y-x>yk-xk

(采用线段树1找最小y+x,第一关键字有序y-x,第二关键字子树最小y+x)

如果点(x,y)在Ps的R2区域内,则:

1.       y≥yk

2.       y-x<yk-xk

(采用线段树1找最小y+x,第一关键字有序y-x,第二关键字子树最小y+x)

如果点(x,y)在Ps的R3区域内,则:

1.       y<=yk

2.       y+x> yk+xk

(可以采用线段树2找最小y+x,关键字就是y+x)

如果点(x,y)在Ps的R4区域内,则:

1.       x≥xk

2.       y+x<yk+xk

(可以采用线段树2找最小y+x,关键字就是y+x)

处理R1的时候,任意时刻处理Pk,我们希望找T中第一关键字大于某常数的第二关键字最小元素;处理R2的时候,任意时刻处理Pk,我们要找的就是T中第一关键字小于某常数的第二关键字最小元素。

这样我们只要处理R1、R2、R3、R4这4种情况即可。时间复杂度的常系数从8降低到了4。

我们按照这样的方法建立的离散图至多含有4n条边。对该图求最小生成树的时间复杂度为O(nlogn);之前建图的复杂度也是O(nlogn),所以总时间复杂度O(nlogn)。空间复杂度O(n)。

总结

这个题目最值得称道的地方就是“分区域”。“分区域”充分利用了平面性质,结合一般情况下最小生成树都具有的环切性质,该方法取得了奇效。

平面曼哈顿最小生成树相关推荐

  1. POJ-3241 Object Clustering 曼哈顿最小生成树

    题目链接:http://poj.org/problem?id=3241 题意:平面上有n个点集,现在把他们分成k个集合,使得每个集合中的每个点都至少有一个本集合的点之间的曼哈顿距离不大于X,求最小的X ...

  2. 曼哈顿距离最小生成树莫队算法

    参考资料:https://www.cnblogs.com/CsOH/p/5904430.html https://blog.csdn.net/huzecong/article/details/8576 ...

  3. 最小生成树(kruskal、prim、最小生成森林问题、严格次小生成树)

    整理的算法模板合集: ACM模板 目录 一.kruskal算法 二.prim算法 三.Boruvka算法 四.生成森林问题(K颗树) 五.最小生成树的唯一性 六.严格次小生成树 LCA优化的次小生成树 ...

  4. BZOJ 4242 水壶(BFS建图+最小生成树+树上倍增)

    题意 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入建筑 ...

  5. 用python实现(1.求输入的百倍,十位,个位数;2.输入a,b和ab间夹角,计算c边长;3.计算两点间曼哈顿距离;4.计算给定数据的几何平均数;5.计算向量的L1和L2范数)

    import math from random import choices from functools import reduce print("1.获取输入整数的百位,十位,个位数(无 ...

  6. ACM 全部算法总结

    ACM 所有算法 附带我学过的算法的博客链接 数据结构 栈 队列 链表 哈希表 哈希数组 堆 优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平 ...

  7. ACM基础知识及算法

    ACM 算法   难度 数据结构 栈 栈     1 单调栈       队列 一般队列     1 优先队列/单调队列     1 循环队列     2 双端队列     2 链表 一般链表     ...

  8. ACM所有算法大全(持续更新)

    转载自: http://blog.sina.com.cn/s/blog_adb6743801019h29.html ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 ...

  9. 【转】楼天城楼教主的acm心路历程(作为励志用)

    [转]楼天城楼教主的acm心路历程(作为励志用) 利用假期空闲之时,将这几年GCJ,ACM,TopCoder 参加的一些重要比赛作个 回顾.昨天是GCJ2006 的回忆,今天时间上更早一些吧,我现在还 ...

最新文章

  1. 图像处理之目标检测入门总结
  2. HDU 3157 Crazy Circuits(有源汇上下界最小流)
  3. boost::noncopyable介绍
  4. 体验使用node.js创建vue+Element-UI项目
  5. Python PIL库总结
  6. 网页布局(固定与不固定原理)
  7. LIVE555再学习 -- Linux 下编译
  8. 浅谈MyBatis一级缓存
  9. Android WebView常见问题及解决方案汇总
  10. OkHttp实现分析之Websocket
  11. 失眠症的治疗办法有哪几种
  12. 利用正则表达式截取特定字符中间字符
  13. Spring IOC 和 AOP 概览
  14. Shiro授权流程图
  15. docker nginx tomcat mysql_使用docker部署nginx+tomcat架构(2):访问mysql数据库
  16. ssms .net3.5_SSMS 18.4中SQL Server查询存储选项
  17. java二次方程式答案_二次方程式Java?
  18. Python JSONPath示例
  19. thinkphp 中英文网站详解
  20. [2019年国庆专题训练] dp专题训练

热门文章

  1. 基于P2P的局域网即时通信应用
  2. 考研复试408-操作系统简答题整理
  3. GMT、UTC与24时区等时间概念
  4. ROS重装及恢复出厂设置
  5. android监测闹钟,Android上的图像识别:构建一个看到的闹钟
  6. 基于verlog的简单自动售货机设计
  7. 基于微信预约挂号小程序毕业设计毕设作品(4)开题报告
  8. 【LaTeX教程】八.Elsevier模板添加作者简介
  9. 三菱变频器控制方式负载特征点
  10. ECharts gauge制作钟表