您的位置:首页 > 移动开发 > Objective-C

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

2015-06-12 12:52 393 查看
Object Clustering

Time Limit: 2000MSMemory Limit: 131072K
Total Submissions: 1641Accepted: 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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: