Object Clustering
Time Limit: 2000MS |
|
Memory Limit: 131072K |
Total Submissions: 1732 |
|
Accepted: 432 |
Description
We have N (n≤10000) objects, and wish to classify them into several groups by judgement of their resemblance. To simply the model with each object having 2 indexes A and B (A, b≤500). The resemblance of Object I and object j is defined by Dij = |ai-aj| + |bi-bj|, and then we say I am dij resemble to J. Now we want to find the minimum value of X, so then we can classify the N objects into K (K < N) groups, and by each GR OUP, one object is at a resemble to another object with the same group, i.e, for every object I, if I are not the only m Ember of the group, then there exists one object J (i≠j) in the same group that satisfies dij≤x
Input
The first line contains the integers N and K. The following N lines each contain, integers a and B, which describe a object.
Output
A single line contains the minimum X.
Sample Input
6 2
1 2
2 3
2 2
3 4
4 3
3 1
Sample Output
2
Source POJ monthly--2007.08.05, Li, Haoyuan ready-made things, do not write their own.
Reprint please indicate the source, thank you http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove There are some points in the two-dimensional plane, the distance between two points is Manhattan distance, and the minimum spanning tree is obtained. Simple n points, can only be done O (n^3) or O (n^2 lgn). But the MST for this Manhattan distance. One of the properties is that for a certain point, the area centered on him is divided into 8 quadrants, and for each quadrant, only the nearest point-edge is taken. In this case, because the edge is bidirectional, so for each point only need to consider 4 directions, the number of edges is O (4*n), and then use Kruskal can do O (NLGN). As for the proof:
This conclusion can be proved as follows: Suppose we build a system with point A as the origin, considering any two points B (x1,y1) and C (X2,y2) in the 45-degree area to the right of the y-axis, it is advisable to set | ab|≤| ac| (the distance here is Manhattan distance), as shown below:
| ab|=x1+y1,| ac|=x2+y2,| bc|=|x1-x2|+|y1-y2|. And because B and C are in the Y axis 45 degrees to the right of the area, there are y-x>0 and x>0. Here we discuss the situation:
1. X1>x2 and Y1>y2. this with | ab|≤| ac| contradiction;
2. X1≤x2 and Y1>y2. At this time | bc|=x2-x1+y1-y2,| ac|-| Bc|=x2+y2-x2+x1-y1+y2=x1-y1+2*y2. The various relationships in front can be y1>y2>x2>x1. hypothesis | ac|<| Bc| is y1>2*y2+x1, then | ab|=x1+y1>2*x1+2*y2,| ac|=x2+y2<2*y2<| Ab| and the premise contradiction, therefore | ac|≥| bc|;
3. X1>x2 and Y1≤y2. In the same vein as 2;
4. X1≤x2 and Y1≤y2. At this time obviously have | ab|+| bc|=| Ac|, that is | ac|>| bc|.
Comprehensive | ac|≥| Bc|, that is, in this area just select the nearest point to a edge of a. Turn from: http://blog.csdn.net/huzecong/article/details/8576908 So if you have a conclusion, how to filter out the nearest point of each region is first 8 directions, because of the bidirectional nature of the edges, We only need to consider 4 directions for one point. These 4 directions (for example, to the right of the y-axis) can be transformed into an area by coordinates (e.g. y>x). About Y=x or y=0 symmetry can be achieved. For y>x This area, if there is a point B (x1,y1) in this area for point A (x0,y0). So x1>x0&&y1-x1>y0-x0. Dist (A, B) =x1-x0+y1-y0=x1+y1-(X0+Y0), then for Point A, is to find the x1+y1 smallest point within the region. So what kind of points satisfied in this area, (x1>x0&&y1-x1>y0-x0) is the condition we will coordinate by x sort, will y-x discretization, with bit to maintain, query for a certain X0, query than (y0-x0) large x1+ Y1 the smallest point. Adding this edge, repeating 4 areas, is Kruskal.
My method: The principle is used above.
When implemented, it is also the area of computing y>x. But the tree array is sorted by the results of X-y discretization.
Because y ' x ' > Y-x
So x ' Y ' < xy
In fact, the tree-like array can not only implement the prefix and, can also implement suffixes and, there is no need to reverse. But I'm just used to it.
#include <iostream> #include <cstring> #include <cstdio> #include <math.h> #include <
Algorithm> #include <vector> using namespace std;
#define MAXN 10007 #define INF 100000000 #define MAXM int POS[MAXM],TREE[MAXM];
void Add (int p,int val,int ID) {while (P < MAXM) {if (Val < tree[p]) {tree[p] = val;
POS[P] = ID;
} p + = p& (-p);
}} int query (int p) {int id=-1,val=inf;
while (P > 0) {if (Tree[p] < val) {val = tree[p];
id = pos[p];
} P-= p& (-p);
} return ID;
} struct node{int x,y,id,xsy;};
int comp (Node A,node b) {if (a.x = = b.x) return a.y > B.y;
return a.x > b.x;
} int Compxsy (Node A,node b) {return a.xsy < b.xsy;} struct edge{int u,v,w;
Edge (int _u=0,int _v=0,int _w=0) {u =_u,v=_v,w=_w;
}
};
Vector<edge> Edge;
Node POINT[MAXN];
Node P[MAXN]; int dist (Node a,node b{return abs (a.x-b.x) +abs (A.Y-B.Y),} void Manhaton (int n) {for (int i = 0;i < n; i++) Point[i].xsy = P
OINT[I].X-POINT[I].Y;
Sort (point,point+n,compxsy);
int cnt = 1,f=-inf;
for (int i = 0;i < n; i++) {if (point[i].xsy! = f) {cnt++;
f = point[i].xsy;
} point[i].xsy = cnt;
} sort (Point,point+n,comp);
for (int i = 0;i < MAXM; i++) tree[i] = Inf,pos[i]=-1;
for (int i = 0;i < n; i++) {int u = point[i].id;
int v = query (point[i].xsy);
if (v! =-1) edge.push_back (Edge (U,v,dist (P[U],P[V)));
Add (Point[i].xsy,point[i].x+point[i].y,u);
}} void Buildedge (int n) {edge.clear ();
for (int j = 0;j < 4; j + +) {for (int i = 0;i < n; i++) point[i] = P[i];
for (int i = 0;i < n; i++) {if (j = = 1) swap (POINT[I].X,POINT[I].Y);
else if (j = = 2) point[i].y =-POINT[I].Y; else if (j==3) {swap (POINT[I].X,POINT[I].Y);
Point[i].y =-POINT[I].Y;
}} Manhaton (n);
}} int PRE[MAXN];
int find (int u) {if (U = = pre[u]) return u;
return Pre[u] = find (Pre[u]); } int Compedge (Edge A,edge b) {return A.W < B.W;} int MST (int n,int k) {for (int i = 0;i < n; i++) p
Re[i] = i;
Sort (Edge.begin (), Edge.end (), Compedge);
int d = 0;
for (int i = 0;i < Edge.size (); i++) {if (n = = k) return D;
D = EDGE[I].W;
int f1 = find (EDGE[I].U);
int F2 = find (EDGE[I].V);
if (f1 = = F2) continue;
PRE[F1] = F2;
n--;
} return D;
} int main () {int n,k; while (scanf ("%d%d", &n,&k)!=eof) {for (int i = 0;i < n; i++) {scanf ("%d%d", &p[i].x,&p
[I].Y];
P[i].id = i;
} buildedge (n);
printf ("%d\n", MST (n,k));
} return 0;
}