• POJ 3241Object Clustering曼哈顿距离最小生成树


    Object Clustering

    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
    Source

    POJ Monthly–2007.08.05, Li, Haoyuan
    题解

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<bitset>
    #include<set>
    #include<stack>
    #include<map>
    #include<list>
    #include<new>
    #include<vector>
    #define MT(a,b) memset(a,b,sizeof(a));
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double pi=acos(-1.0);
    const double E=2.718281828459;
    const ll mod=1e8+7;
    const int INF=0x3f3f3f3f;
     
    int n,k;
     
    struct node{
        int x;
        int y;
        int id;
        bool friend operator<(node a,node b){
            return a.x==b.x?a.y<b.y:a.x<b.x;
            ///保证树状数组更新和查询时不会遗漏
        }
    }point[10005];
     
    struct edge{
        int s;
        int e;
        int c;
        bool friend operator<(edge a,edge b){
            return a.c<b.c;
        }
    }load[40000];
    int sign=0;
    int p[10005];
    int find(int x){
        return p[x]==x?x:p[x]=find(p[x]);
    }
     
    void kruskal(){
        for(int i=1;i<=n;i++)
            p[i]=i;
        sort(load+1,load+1+sign);
        int cnt=0;
        for(int i=1;i<=sign;i++){
            int x=find(load[i].s);
            int y=find(load[i].e);
            if(x!=y){
                cnt++;
                p[x]=y;
                if(cnt==n-k){
                    printf("%d
    ",load[i].c);
                    return ;
                }
            }
        }
    }
     
    int id[10005]; ///y-x为索引的编号
    int xy[10005]; ///y-x为索引 x+y的最小值
     
    void update(int index,int minn,int s)   ///index:y-x  minn:x+y   s:编号
    {
        index+=1000;
        for(int i=index;i>=1;i-=(i&(-i))){
            if(xy[i]>minn){
                xy[i]=minn;
                id[i]=s;
            }
        }
    }
     
    void query(int index,int minn,int s)    ///index:y-x  minn:x+y   s:编号
    {
        index+=1000;
        int e=-1,c=INF;
        ///现在以编号s为原点,查询y-x>=index的点中x+y的最小值
        for(int i=index;i<10000;i+=(i&(-i))){
            if(xy[i]<c){
                e=id[i];
                c=xy[i];
            }
        }
        if(e!=-1)
            load[++sign]=edge{s,e,c-minn};
    }
     
    void build_edge()
    {
        /// 以(xi,yi)为原点,对于第1区域内的点(x,y)满足条件
        /// x>=xi,y-x>=yi-xi,(x+y)最小
        sort(point+1,point+1+n);
        memset(id,-1,sizeof(id));
        fill(xy,xy+10005,INF);
        ///按照x升序
        ///保证后面查询时,x都比当前的x大
        for(int i=n;i>=1;i--){
            int index=point[i].y-point[i].x;
            int minn=point[i].x+point[i].y;
            query(index,minn,point[i].id);
            update(index,minn,point[i].id);
        }
    }
     
    int main()      ///第K大边
    {
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n;i++){
            scanf("%d %d",&point[i].x,&point[i].y);
            point[i].id=i;
        }
        ///1象限建边
        build_edge();
     
        ///2象限建边
        for(int i=1;i<=n;i++)
            swap(point[i].x,point[i].y);
        build_edge();
     
        ///3象限建边
        for(int i=1;i<=n;i++)
            point[i].x=-point[i].x;
        build_edge();
     
        ///4象限建边
        for(int i=1;i<=n;i++)
            swap(point[i].x,point[i].y);
        build_edge();
        kruskal();
        return 0;
    }
    
  • 相关阅读:
    加入创业公司有什么利弊
    Find Minimum in Rotated Sorted Array II
    Search in Rotated Sorted Array II
    Search in Rotated Sorted Array
    Find Minimum in Rotated Sorted Array
    Remove Duplicates from Sorted Array
    Spiral Matrix
    Spiral Matrix II
    Symmetric Tree
    Rotate Image
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798685.html
Copyright © 2020-2023  润新知