Time Limit: 2000MS | Memory Limit: 131072K | |
Total Submissions: 1641 | Accepted: 401 |
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 object has 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 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 (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
题意:构造曼哈顿最小生成树,求出它的第k+1大边。
思路:参见http://blog.csdn.net/huzecong/article/details/8576908
AC代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y,pos;
}point[10010];
struct node2
{
int u,v,w;
}edge[40010];
int N=2020,n,K,tot,p[10010],c[2020],d[2020],INF=1e9;
bool cmp(node a,node b)
{
return a.x<b.x ||(a.x==b.x && a.y<b.y);
}
bool cmp2(node2 a,node2 b)
{
return a.w<b.w;
}
int lowbit(int x)
{
return x&(-x);
}
int find(int x)
{
return x==p[x] ? x : p[x]=find(p[x]);
}
void query(int val,int w,int pos)
{
int id=-1,minn=INF,i;
val+=1010;
for(i=val;i<N;i+=lowbit(i))
if(c[i]<minn)
{
minn=c[i];
id=d[i];
}
if(id!=-1)
{
tot++;
edge[tot].u=pos;
edge[tot].v=id;
edge[tot].w=minn-w;
}
}
void update(int val,int w,int pos)
{
int i,j,k;
val+=1010;
for(i=val;i>0;i-=lowbit(i))
{
if(w<c[i])
{
c[i]=w;
d[i]=pos;
}
}
}
void go()
{
// 排序,从右往左处理,寻找y-x~N范围内具有最小y+x值的点的id,这里用的树状数组
int i,j,k;
sort(point+1,point+1+n,cmp);
for(i=1;i<N;i++)
c[i]=INF;
for(i=n;i>=1;i--)
{
query(point[i].y-point[i].x,point[i].y+point[i].x,point[i].pos);
update(point[i].y-point[i].x,point[i].y+point[i].x,point[i].pos);
}
}
int work()
{
int i,j,k=0,u,v;
if(K==0)
return 0;
go();// (x,y)
for(i=1;i<=n;i++)
swap(point[i].x,point[i].y);
go();// (y,x)
for(i=1;i<=n;i++)
point[i].y=-point[i].y;
go();// (y,-x)
for(i=1;i<=n;i++)
swap(point[i].x,point[i].y);
go();// (-x,y)
sort(edge+1,edge+1+tot,cmp2);
for(i=1;i<=n;i++)
p[i]=i;
for(i=1;i<=tot;i++)
{
u=find(edge[i].u);
v=find(edge[i].v);
if(u==v)
continue;
k++;
p[u]=v;
if(k==K)
return edge[i].w;
}
}
int main()
{
int i,j,k,ans;
scanf("%d%d",&n,&K);
K=n-K;
for(i=1;i<=n;i++)
{
scanf("%d%d",&point[i].x,&point[i].y);
point[i].pos=i;
}
ans=work();
printf("%d\n",ans);
}