• 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;
    }
    
  • 相关阅读:
    [SDOI 2009] 晨跑
    [ZJOI 2009] 假期的宿舍
    [BZOJ 2006] 狼抓兔子
    [BZOJ 1691] 挑剔的美食家
    [HNOI 2015] 菜肴制作
    [Codeforces 489E] Nastya and King-Shamans
    sum(sum(abs(y))) 中 sum(sum())什么意思?
    matlab 函数 bwarea
    系统启动挂载根文件系统时Kernel panic
    rmmod: chdir(/lib/modules): No such file or directory
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798685.html
Copyright © 2020-2023  润新知