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 }
View Code

 

你可能感兴趣的:(cluster)