POJ 3241 Object Clustering(Manhattan MST)

题目链接:http://poj.org/problem?id=3241

Description

We have (N ≤ 10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simply the model, each object has 2 indexes a and b (ab ≤ 500). The resemblance of object i and object j is defined by dij = |a- aj| + |b- bj|, and then we say i is dij resemble to j. Now we want to find the minimum value of X, so that we can classify the N objects into K (< N) groups, and in each group, one object is at most X resemble to another object in the same group, i.e, for every object i, if i is not the only member of the group, then there exists one object j (i ≠ j) in the same group that satisfies dij ≤ X

Input

The first line contains two integers N and K. The following N lines each contain two integers a and b, which describe a object.

Output

A single line contains the minimum X.

题目大意:给n个点,两个点之间的距离为曼哈顿距离。要求把n个点分成k份,每份构成一个连通的子图(树),要求最大边最小。求最大边的最小值。

思路:实际上就是求平面上曼哈顿距离的最小生成树的第k大边(即减掉最大的k-1条边构成k份)。

资料:曼哈顿MST。复杂度O(nlogn)。

http://wenku.baidu.com/view/1e4878196bd97f192279e941.html

http://blog.csdn.net/huzecong/article/details/8576908

代码(79MS):

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 typedef long long LL;
  7 #define FOR(i, n) for(int i = 0; i < n; ++i)
  8
  9 namespace Bilibili {
 10     const int MAXV = 10010;
 11     const int MAXE = MAXV * 4;
 12
 13     struct Edge {
 14         int u, v, cost;
 15         Edge(int u = 0, int v = 0, int cost = 0):
 16             u(u), v(v), cost(cost) {}
 17         bool operator < (const Edge &rhs) const {
 18             return cost < rhs.cost;
 19         }
 20     };
 21
 22     struct Point {
 23         int x, y, id;
 24         void read(int i) {
 25             id = i;
 26             scanf("%d%d", &x, &y);
 27         }
 28         bool operator < (const Point &rhs) const {
 29             if(x != rhs.x) return x < rhs.x;
 30             return y < rhs.y;
 31         }
 32     };
 33
 34     Point p[MAXV];
 35     Edge edge[MAXE];
 36     int x_plus_y[MAXV], y_sub_x[MAXV];
 37     int n, k, ecnt;
 38
 39     int hash[MAXV], hcnt;
 40
 41     void get_y_sub_x() {
 42         for(int i = 0; i < n; ++i) hash[i] = y_sub_x[i] = p[i].y - p[i].x;
 43         sort(hash, hash + n);
 44         hcnt = unique(hash, hash + n) - hash;
 45         for(int i = 0; i < n; ++i) y_sub_x[i] = lower_bound(hash, hash + hcnt, y_sub_x[i]) - hash + 1;
 46     }
 47
 48     void get_x_plus_y() {
 49         for(int i = 0; i < n; ++i) x_plus_y[i] = p[i].x + p[i].y;
 50     }
 51
 52     int tree[MAXV];
 53     int lowbit(int x) {
 54         return x & -x;
 55     }
 56
 57     void update_min(int &a, int b) {
 58         if(b == -1) return ;
 59         if(a == -1 || x_plus_y[a] > x_plus_y[b])
 60             a = b;
 61     }
 62
 63     void initBit() {
 64         memset(tree + 1, -1, hcnt * sizeof(int));
 65     }
 66
 67     void modify(int x, int val) {
 68         while(x) {
 69             update_min(tree[x], val);
 70             x -= lowbit(x);
 71         }
 72     }
 73
 74     int query(int x) {
 75         int res = -1;
 76         while(x <= hcnt) {
 77             update_min(res, tree[x]);
 78             x += lowbit(x);
 79         }
 80         return res;
 81     }
 82
 83     void build_edge() {
 84         sort(p, p + n);
 85         get_x_plus_y();
 86         get_y_sub_x();
 87         initBit();
 88         for(int i = n - 1; i >= 0; --i) {
 89             int tmp = query(y_sub_x[i]);
 90             if(tmp != -1) edge[ecnt++] = Edge(p[i].id, p[tmp].id, x_plus_y[tmp] - x_plus_y[i]);
 91             modify(y_sub_x[i], i);
 92         }
 93     }
 94
 95     int fa[MAXV], ans[MAXV];
 96
 97     int find_set(int x) {
 98         return fa[x] == x ? x : fa[x] = find_set(fa[x]);
 99     }
100
101     int kruskal() {
102         for(int i = 0; i < n; ++i) fa[i] = i;
103         sort(edge, edge + ecnt);
104         int acnt = 0;
105         for(int i = 0; i < ecnt; ++i) {
106             int fu = find_set(edge[i].u), fv = find_set(edge[i].v);
107             if(fu != fv) {
108                 ans[acnt++] = edge[i].cost;
109                 fa[fu] = fv;
110             }
111         }
112         reverse(ans, ans + acnt);
113         return ans[k - 1];
114     }
115
116     void mymain() {
117         scanf("%d%d", &n, &k);
118         for(int i = 0; i < n; ++i) p[i].read(i);
119
120         build_edge();
121         for(int i = 0; i < n; ++i) swap(p[i].x, p[i].y);
122         build_edge();
123         for(int i = 0; i < n; ++i) p[i].x = -p[i].x;
124         build_edge();
125         for(int i = 0; i < n; ++i) swap(p[i].x, p[i].y);
126         build_edge();
127
128         printf("%d\n", kruskal());
129     }
130 }
131
132 int main() {
133     Bilibili::mymain();
134 }

时间: 2024-10-11 08:43:14

POJ 3241 Object Clustering(Manhattan MST)的相关文章

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

平面点曼哈顿最小生成树——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

POJ 3241 Object Clustering 莫队算法

第n-k大曼哈顿距离,莫队算法裸题 Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 1584   Accepted: 366 Description We have N (N ≤ 10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simp

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

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

POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树

题目链接:点击打开链接 题意: 给定二维平面上的n个点坐标,常数k 下面n行给出坐标 求一个最小生成树,问第k大的边是多少. 任意两个点间建一条边的花费是其曼哈顿距离. 思路:转自:点击打开链接 一.曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下: 给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价. 朴素的算法可以用O(N2)的Prim,或者处理出所有边做Kruskal,但在这里总边数有O(N2)条,所以Kruskal的复杂度变成了O(N2logN

POJ 3241 Object Clustering 曼哈顿距离最小生成树

题目大意:求出曼哈顿距离最小生成树上的第k大边权. 思路:首先,你要了解:http://blog.csdn.net/acm_cxlove/article/details/8890003 也就是说,我们以每一个点为中心,把平面分成8个部分,每一个部分我们只需要离这个点最近的点.然后加上建一条边连接这个边和最近的点.然后就是MST. 听说这个算法是莫队算法的基础,我现在就去学. CODE: #include <cstdio> #include <cstring> #include &l

HDU 1102 &amp;&amp; POJ 2421 Constructing Roads (经典MST~Prim)

链接:http://poj.org/problem?id=2421  或   http://acm.hdu.edu.cn/showproblem.php?pid=1102 Problem Description There are N villages, which are numbered from 1 to N, and you should build some roads such that every two villages can connect to each other. We

poj 1789 Truck History(kruskal算法)

题目链接:http://poj.org/problem?id=1789 思路:把每一行看成一个一个点,每两行之间不懂得字符个数就看做是权值.然后用kruskal算法计算出最小生成树 我写了两个代码一个是用优先队列写的,但是超时啦,不知道为什么,希望有人可以解答.后面用的数组sort排序然后才AC. code: 数组sort排序AC代码: #include<cstdio> #include<queue> #include<algorithm> #include<io

POJ - 3352 Road Construction(边双连通分支)

1.给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 2.POJ - 3177 Redundant Paths(边双连通分支)(模板)  与这道题一模一样.代码就改了下范围,其他都没动... 3. //边双连通分支 /* 去掉桥,其余的连通分支就是边双连通分支了.一个有桥的连通图要变成边双连通图的话, 把双连通子图收缩为一个点,形成一颗树.需要加的边为(leaf+1)/2(leaf为叶子结点的个数) POJ 3177 给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图