1213 二维曼哈顿距离最小生成树
基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题

 收藏
 关注

二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离)。求这N个点所组成的完全图的最小生成树的边权之和。
Input
第1行:1个数N,表示点的数量。(2 <= N <= 50000)
第2 - N + 1行:每行2个数,表示点的坐标(0 <= x, y <= 1000000)
Output
输出N个点所组成的完全图的最小生成树的边权之和。
Input示例
3
0 0
1 0
1 1
Output示例
2

所以我们只要求一个点在其45°角的区域内离他最近的点就行了,而这可以用线段树或树状数组解决

我们以y轴正半轴往右偏45°角的区域为例:

点j在点i的这个区域要满足的条件是:

yj-xj>yi-xi

且xj>xi

那么我们将点以x为第一关键字,y为第二关键字,排序后倒序插入线段树

线段树的线段这一维是离散后的y-x,值是y+x

我们要求的是大于yi-xi的最小的y+x,而xj>xi这个条件已经由插入顺序满足了

这样我们成功的解决了这个区域的点

而其他区域的点我们可以通过坐标变换转移到这个区域

由于对称性,我们注意到其实只要求x轴或y轴正半轴所在的四个区域就行了

那么这个问题就这样解决了

#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <cstdio>
#include <memory>
#include <cctype>
#include <bitset>
#include <string>
#include <vector>
#include <climits>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <functional>//#define FIN freopen("input.txt","r",stdin);
//#define FOUT freopen("output.txt","w+",stdout);
using namespace std;
typedef long long ll;const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps=1e-8;
const double Pi=acos(-1.0);
const int N=50010;struct point
{int x,y,id;bool operator<(const point p)const{return x!=p.x?x<p.x:y<p.y;}
} p[N];
struct BIT
{int min_val,pos;void init(){min_val=INF;pos=-1;}
} bit[N];
int par[N];//并查集中父亲
int hight[N];//并查集树的高度
struct edge
{int u,v,cost;
};
edge G[N<<2];//边集(边数)
int V,E;//顶点数和边数
int get_Manhadm_dis(point a,point b)
{return abs(a.x-b.x)+abs(a.y-b.y);
}
void addedge(int u,int v,int w)
{G[E].u=u;G[E].v=v;G[E++].cost=w;
}
int lowbit(int x)
{return x&(-x);
}
void update(int x,int val,int pos)
{for(int i=x; i>=1; i-=lowbit(i))if(val<bit[i].min_val){bit[i].min_val=val;bit[i].pos=pos;}
}
int ask(int x,int m)
{int min_val=INF;int pos=-1;for(int i=x; i<=m; i+=lowbit(i))if(bit[i].min_val<min_val){min_val=bit[i].min_val;pos=bit[i].pos;}return pos;
}
void make_edge()
{int a[N],b[N];for(int dir=0; dir<4; dir++){if(dir==1||dir==3)for(int i=0; i<V; i++)swap(p[i].x,p[i].y);else if(dir==2)for(int i=0; i<V; i++)p[i].x=-p[i].x;sort(p,p+V);for(int i=0; i<V; i++)a[i]=b[i]=p[i].y-p[i].x;sort(b,b+V);int m=unique(b,b+V)-b;for(int i=1; i<=m; i++)bit[i].init();for(int i=V-1;i>=0; i--){int pos=lower_bound(b,b+m,a[i])-b+1;int ans=ask(pos,m);if(ans!=-1)addedge(p[i].id,p[ans].id,get_Manhadm_dis(p[i],p[ans]));update(pos,p[i].x+p[i].y,i);}}
}
//并查集初始化
void Init_union_find(int n)
{for(int i=0; i<n; i++){par[i]=i;hight[i]=0;}
}
//查询树的根
int find(int x)
{if(par[x]==x)return x;elsereturn par[x]=find(par[x]);
}
//合并x和y所属的集合
void unite(int x,int y)
{x=find(x);y=find(y);if(x==y)return ;if(hight[x]<hight[y])par[x]=y;else{par[y]=x;if(hight[x]==hight[y])hight[x]++;}
}
//判断x和y是否属于同一个集合
bool same(int x,int y)
{return find(x)==find(y);
}
bool cmp(const edge& a,const edge& b)
{return a.cost<b.cost;
}
int kruskal()
{sort(G,G+E,cmp);//按照edge.cost的顺序从小到大排列Init_union_find(V);//并查集初始化int ans=0;for(int i=0; i<E; i++){edge e=G[i];if(!same(e.u,e.v)){unite(e.u,e.v);ans+=e.cost;}}return ans;
}
int main()
{scanf("%d",&V);for(int i=0; i<V; i++){scanf("%d %d",&p[i].x,&p[i].y);p[i].id=i+1;}E=0;make_edge();printf("%d\n",kruskal());
}

51nod 1213 二维曼哈顿距离最小生成树相关推荐

  1. 51nod 1213 二维曼哈顿距离最小生成树 树状数组+最小生成树

    Description 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离). ...

  2. 曼哈顿距离最小生成树与莫队算法(总结)

    曼哈顿距离最小生成树与莫队算法(总结) 1 曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下:  给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价.  朴 ...

  3. 曼哈顿距离最小生成树

    一.参考博客 博客:曼哈顿距离最小生成树与莫队算法 博客:学习总结:最小曼哈顿距离生成树 二.前置知识 1.曼哈顿距离:给定二维平面上的N个点,在两点之间连边的代价.(即distance(P1,P2) ...

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

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

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

    一.曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下: 给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价. 朴素的算法可以用O(N2)的Prim,或者处理 ...

  6. 图论 —— 生成树 —— 曼哈顿距离最小生成树

    [概述] 当给出一些二维平面的点时,记两点间距离为曼哈顿距离,此时的最小生成树,称为曼哈顿最小距离生成树. 对于 n 个点来说,最朴素的做法是暴力求出所有所有点两两之间的曼哈顿距离,然后再跑最小生成树 ...

  7. 计算几何 —— 二维几何基础 —— 距离度量方法

    [概述] 在数据挖掘中,经常需要计算样本之间的相似度,通常做法是计算样本之间的距离. 比如判断 A.B.C 三种商品之间的相似性,可以先按照商品特征构建 A.B.C 各自的向量,然后求向量间的距离,距 ...

  8. java 课后习题 二维坐标距离 三角形判断等

    知识点: 1.三角形的判断公式 两边之和大于第三边 2.二维坐标两点距离公式 根号[(x1-x2)平方+(y1-y2)平方] 3.JAVA Math.pow(变量,指数); 的运用 4.JAVA Ma ...

  9. 【JAVA 第四章 流程控制语句】课后习题 二维坐标距离 三角形判断等

    知识点: 1.三角形的判断公式 两边之和大于第三边 2.二维坐标两点距离公式 根号[(x1-x2)平方+(y1-y2)平方] 3.JAVA Math.pow(变量,指数); 的运用 4.JAVA Ma ...

最新文章

  1. AD下批量导入域用户
  2. 查看mysql版本的四种方法
  3. JSP指令与动作——include forward param
  4. JavaScript学习笔记(七)——函数的定义与调用
  5. Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
  6. java web mvc思想介绍
  7. 浮点转字符串性能比较
  8. 历届奥运会中国金牌数
  9. nyoj-228(士兵杀敌五) hdu-1556 Color the ball
  10. 全国计算机等级考试题库二级C操作题100套(第38套)
  11. 阿里云超算异构Spot集群,助力深势科技30%成本驱动MDaaS海量算力
  12. 企业数据化应用的第一步,你需要报表管理平台
  13. tensorflow-yolo3系列配置文章汇总
  14. beta阶段——项目复审
  15. 任正非谈鸿蒙系统06 新闻,任正非首谈华为鸿蒙操作系统:很有可能比安卓和苹果还要快!...
  16. 解决办法:开机后过很长时间键盘才能用
  17. c语言中优先级顺序表
  18. CDOJ 1131 男神的礼物 区间dp
  19. 计算机管理器鼠标不见了怎么办,电脑的鼠标光标消失了
  20. easyopenjtag使用教程(最新版)

热门文章

  1. Ubuntu实现划词翻译
  2. Spring Web Flow 2中的流管理持久性
  3. 计蒜客 T1853:非常男女(前缀和)
  4. 人在江湖,以“核”为贵
  5. python数据可视化第七节(绘制3D图表和统计地图)
  6. springboot 实现redis高并发抢票服务
  7. 几何光学学习笔记(7)- 3.1 理想光学系统
  8. 蓝鸽服务器崩溃怎样从装系统,系统崩溃如何重装系统?
  9. 利用Photoshop通道制作BMP格式的透明图标
  10. QT:为图片加当前系统时间水印