51nod 1213 二维曼哈顿距离最小生成树
来源:互联网 发布:mac安装win10镜像 编辑:程序博客网 时间:2024/06/05 12:34
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示例
30 01 01 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; else return 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());}
阅读全文
0 0
- 51NOD 1213 二维曼哈顿距离最小生成树
- 51nod 1213 二维曼哈顿距离最小生成树
- 51nod 1213 二维曼哈顿距离最小生成树 树状数组
- bzoj2177/51nod-1213 曼哈顿距离最小生成树
- 二维平面曼哈顿距离最小生成树模版
- [poj 3241]二维曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- 二维曼哈顿最小生成树
- POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树
- [BZOJ2177][最小/最大(曼哈顿距离)生成树]曼哈顿最小生成树
- 关于曼哈顿距离下的最小生成树
- 曼哈顿距离最小生成树与莫队算法
- POJ 3241 Object Clustering (曼哈顿距离最小生成树)
- 曼哈顿距离最小生成树与莫队算法
- POJ 3241 Object Clustering 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树与莫队算法
- python,UPD,socket(一) 使用udp 发送消息
- CentOS通过yum安装Mariadb(MySQL)无法启动服务或者找不到mysql.sock(2)
- 文章标题
- CPP
- poi 导入Excel封装 并处理数据类型
- 51nod 1213 二维曼哈顿距离最小生成树
- hdoj 1015 Safecracker
- 将自己已有的github库迁移到ubuntu系统下
- [CDN 技术] HTTP参数中Etag的重要性
- Bone Collector -简单01背包
- 一次应用访问数据库 IP 配成外网 IP 引发的血案
- [已解决]Attempt to invoke virtual method 'int android.view.View.getImportantForAccessibility()'
- 约瑟夫环,数三退一类问题(数组解法)
- Ubuntu下搭建VPN服务器的方法