老oj曼哈顿最小生成树

Description

平面坐标系xOy内,给定n个顶点V = (x , y)。对于顶点u、v,u与v之间的距离d定义为|xu – xv| + |yu – yv|
你的任务就是求出这n个顶点的最小生成树。

Input

第一行一个正整数n,表示定点个数。

接下来n行每行两个正整数x、y,描述一个顶点。

Output

只有一行,为最小生成树的边的距离和。

Sample Input

4
1 0
0 1
0 -1
-1 0

Sample Output

6

[数据约定]
对于30%的数据n <= 2000;
对于50%的数据n <= 5000;
对于100%的数据n <= 50000;
0 <= x, y <= 100000。

题解:http://blog.csdn.net/acm_cxlove/article/details/8890003code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define maxn 50005
 7 #define inf 1061109567
 8 using namespace std;
 9 char ch;
10 bool ok;
11 void read(int &x){
12     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
13     for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
14     if (ok) x=-x;
15 }
16 int n,m,ans=0;
17 struct Point{
18     int x,y,d,id;
19 }point[maxn],tmp[maxn];
20 bool cmp1(Point a,Point b){
21     if (a.x!=b.x) return a.x>b.x;
22     return a.y>b.y;
23 }
24 int calc(Point a,Point b){return abs(a.x-b.x)+abs(a.y-b.y);}
25 struct Edge{
26     int u,v,c;
27 }edge[maxn<<2];
28 bool cmp2(Edge a,Edge b){return a.c<b.c;}
29 int cntd,d[maxn];
30 struct DATA{
31     int val,pos;
32     void init(){val=inf,pos=-1;}
33     void update(DATA b){if (val>b.val) val=b.val,pos=b.pos;}
34 };
35 struct bit{
36     #define lowbit(x) ((x)&(-(x)))
37     DATA node[maxn];
38     void init(){for (int i=1;i<=cntd;i++) node[i].init();}
39     void insert(int x,DATA p){
40         x=cntd-x+1;
41         for (int i=x;i<=cntd;i+=lowbit(i)) node[i].update(p);
42     }
43     int query(int x){
44         x=cntd-x+1;
45         DATA ans; ans.init();
46         for (int i=x;i;i-=lowbit(i)) ans.update(node[i]);
47         return ans.pos;
48     }
49 }T;
50 void prepare(){
51     for (int i=1;i<=n;i++) d[i]=point[i].y-point[i].x;
52     sort(d+1,d+n+1),cntd=unique(d+1,d+n+1)-d-1;
53     for (int i=1;i<=n;i++) point[i].d=lower_bound(d+1,d+cntd+1,point[i].y-point[i].x)-d;
54     sort(point+1,point+n+1,cmp1);
55     T.init();
56     for (int i=1;i<=n;i++){
57         int u=point[i].id,v=T.query(point[i].d);
58         if (v!=-1) edge[++m]=(Edge){u,v,calc(tmp[u],tmp[v])};
59         T.insert(point[i].d,(DATA){point[i].x+point[i].y,u});
60     }
61 }
62 int fa[maxn];
63 int find(int x){return x==fa[x]?fa[x]:fa[x]=find(fa[x]);}
64 int main(){
65     read(n);
66     for (int i=1;i<=n;i++) read(point[i].x),read(point[i].y),point[i].id=i;
67     for (int i=1;i<=n;i++) tmp[i]=point[i]; prepare();
68     for (int i=1;i<=n;i++) point[i].x=tmp[i].y,point[i].y=tmp[i].x,point[i].id=i; prepare();
69     for (int i=1;i<=n;i++) point[i].x=-tmp[i].y,point[i].y=tmp[i].x,point[i].id=i; prepare();
70     for (int i=1;i<=n;i++) point[i].x=tmp[i].x,point[i].y=-tmp[i].y,point[i].id=i; prepare();
71     sort(edge+1,edge+m+1,cmp2);
72     for (int i=1;i<=n;i++) fa[i]=i;
73     for (int i=1,cnt=0;i<=m&&cnt<n;i++)
74         if (find(edge[i].u)!=find(edge[i].v))
75             fa[find(edge[i].u)]=find(edge[i].v),cnt++,ans+=edge[i].c;
76     printf("%d\n",ans);
77     return 0;
78 }
				
时间: 2024-11-08 07:39:03

老oj曼哈顿最小生成树的相关文章

POJ3241 Object Clustering 曼哈顿最小生成树

题意:转换一下就是求曼哈顿最小生成树的第n-k条边 参考:莫涛大神的论文<平面点曼哈顿最小生成树> /* Problem: 3241 User: 96655 Memory: 920K Time: 94MS Language: C++ Result: Accepted */ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cs

【POJ 3241】曼哈顿最小生成树(模板整理)

关于 曼哈顿最小生成树 的证明见:http://www.2cto.com/kf/201505/399861.html 模板: #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct Point{ int x,y,i

平面点曼哈顿最小生成树——POJ 3241 Object Clustering

对应POJ题目:点击打开链接 Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 1697   Accepted: 418 Description We have N (N ≤ 10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simply

数据结构与算法问题 sdut oj 2144 最小生成树

题目描述 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的.现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市. 输入 输入包含多组数据,格式如下. 第一行包括两个整数n m,代表城市个数和可以修建的公路个数.(n<=100) 剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c. 输出 每组输出占一行,仅输出最小花费. 示例输入 3 2 1 2 1 1 3 1 示例输出 2 #include

曼哈顿最小生成树

1.poj 3241 Object Clustering 题意:平面上有n个点,点之间的距离采用曼哈顿距离衡量.求一个最小距离X,使得在把这些点分为k组后,每组中两两点之间的距离不超过X. 思路:首先我们这么想,如果所有点都在1个组中,即k=1时,那么所要求的X即为该n个点的曼哈顿最小生成树的最大边:当k=2时,如果我们将最小生成树的最大边割开,形成2组,答案仍未原最小生成树的第2大的边(不会比之还小)……以此类推,可转换为求解平面上n个点的曼哈顿距离最小生成树的第k大的边的长度. 接下来,就是

曼哈顿最小生成树 全网最全

好消息,为庆祝自己暑假上蓝,并成功晋级为参赛队员.我决定在这个暑假集训中写一篇研究性报告,像那些国家集训队的人那样,当然质量没有那么高.我假装网上没有直接完整的关于曼哈顿最小生成树资料.于是自己就想做整理和详细解释的工作.后文会放上自己参考的blog,喝水不忘挖井人. 摘    要: 曼哈顿最小生成树,是把最小生成树中两点直线距离的条件改成了在坐标系下的曼哈顿距离的条件. 结    论: 以一个点为原点建立直角坐标系,在每45度内只会向距离该点最近的一个点连边. 算法过程: 我直接就按照算法ru

poj 3241 Object Clustering (曼哈顿最小生成树)

Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2640   Accepted: 806 Description We have N (N ≤ 10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simply the model, each

UVALive 3662 Another Minimum Spanning Tree 曼哈顿最小生成树

题目链接:点击打开链接 题意: 给定二维平面的n个点坐标,问曼哈顿MST 的值. 模版题 #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <vector> #incl

poj 3241 Object Clustering 曼哈顿最小生成树

题意: 平面上有n个点,现在把他们分成k个集合,使得每个集合中的每个点都至少有一个本集合的点之间的曼哈顿距离不大于X,求最小的X. 分析: 转化为求n个点生成完全图的最小生成树的第k大边.接下来有几个重点. 1)根据莫队算法,由于边权是点的曼哈顿距离,每个点只需要跟周围8个方向中每个方向最近的点连边,这样算出的图与用完全图算出的最小生成树一样,涉及的边却大大减少. 2)用树状数组维护y右偏45度的最近点,每个点以y-x的位置,y+x的值放入树状数组,由于每次是查询区间(pos,last)的情况,