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

Object Clustering
 Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 2640 Accepted: 806

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 Nobjects 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.

Sample Input

```6 2
1 2
2 3
2 2
3 4
4 3
3 1
```

Sample Output

`2`

（在平面坐标第一象限）给你n个整点，A(x1,y1)和B(x2,y2)两点之间的距离定义为|x1-x2|+|y1-y2|，求最小生成树第k大边。

```#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=10000;
const int inf=10000;

struct tdot
{
int x,y;
int num;//每个点的序号
int dis;//离散化后的值
};
tdot dot[maxn+10];

//x
int cmp1(tdot a,tdot b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
}

//y-x
int cmp2(tdot a,tdot b)
{
if(a.y-a.x==b.y-b.x)
return a.x<b.x;
return a.y-a.x<b.y-b.x;
}

//离散化及预处理
void discrete(int n)
{
sort(dot+1,dot+n+1,cmp2);
for(int i=1;i<=n;i++)
dot[i].dis=i;
sort(dot+1,dot+n+1,cmp1);
}

struct ttree
{
int l,r;
int num;
int mmin;
};
ttree tree[maxn*4+10];

void pushup(int x)
{
if(tree[x].l==tree[x].r)
return;
if(tree[x*2].mmin<=tree[x*2+1].mmin)
tree[x].mmin=tree[x*2].mmin,tree[x].num=tree[x*2].num;
else
tree[x].mmin=tree[x*2+1].mmin,tree[x].num=tree[x*2+1].num;
}

void build(int x,int l,int r)
{
tree[x].l=l;tree[x].r=r;
tree[x].mmin=inf;
tree[x].num=0;
if(l<r)
{
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
}
}

void modify(int x,int pos,int mmin,int num)
{
if(tree[x].l==tree[x].r)
tree[x].mmin=mmin,tree[x].num=num;
else
{
int mid=(tree[x].l+tree[x].r)/2;
if(pos<=mid)
modify(x*2,pos,mmin,num);
else
modify(x*2+1,pos,mmin,num);
pushup(x);
}
}

struct tret
{
int mmin,num;
};

tret query(int x,int l,int r)
{
tret ret;
ret.mmin=inf;ret.num=0;
if(l<=tree[x].l&&r>=tree[x].r)
{
ret.mmin=tree[x].mmin;
ret.num=tree[x].num;
return ret;
}
int mid=(tree[x].l+tree[x].r)/2;
if(l<=mid)
{
tret ret0=query(x*2,l,r);
if(ret.mmin>ret0.mmin)
ret.mmin=ret0.mmin,ret.num=ret0.num;
}
if(r>mid)
{
tret ret0=query(x*2+1,l,r);
if(ret.mmin>ret0.mmin)
ret.mmin=ret0.mmin,ret.num=ret0.num;
}
return ret;
}

struct tedge
{
int a,b;
int w;
};
tedge edge[maxn*4+10];
int cnt=1;

//加边
{
build(1,1,n);
for(int i=n;i>=1;i--)
{
tret ret=query(1,dot[i].dis,n);
if(ret.num!=0)
{
edge[cnt].a=dot[i].num;
edge[cnt].b=ret.num;
edge[cnt++].w=ret.mmin-dot[i].x-dot[i].y;
}
modify(1,dot[i].dis,dot[i].x+dot[i].y,dot[i].num);
}
}

//kruskal用比较函数
int cmp(tedge a,tedge b)
{
return a.w<b.w;
}

int fa[maxn+10];

int father(int x)
{
if(fa[x]==x)
return x;
return fa[x]=father(fa[x]);
}

int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&dot[i].x,&dot[i].y);
dot[i].num=i;
}

discrete(n);

for(int i=1;i<=n;i++)
swap(dot[i].x,dot[i].y);
discrete(n);

for(int i=1;i<=n;i++)
dot[i].x*=-1;
discrete(n);

for(int i=1;i<=n;i++)
swap(dot[i].x,dot[i].y);
discrete(n);

//kruskal
for(int i=1;i<=n;i++)
fa[i]=i;
sort(edge+1,edge+cnt,cmp);
for(int i=1,j=0;i<cnt;i++)
{
int fx=father(edge[i].a);
int fy=father(edge[i].b);
if(fx!=fy)
{
fa[fx]=fy;
j++;
}
if(j==n-k)
{
printf("%d\n",edge[i].w);
break;
}
}

return 0;
}```
View Code

PS:看别人的解题报告只是一种学习的途径。代码的实现还是要靠自己写。这两者的深度是大不相同的，有些东西只有在自己写代码的时候才能体会到。这道题前前后后写了三遍，终于过了，开心。

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

(0)
(0)