zoukankan      html  css  js  c++  java
  • 图论--曼哈顿距离最小生成树模板

    #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;
    }
    
    
  • 相关阅读:
    挺好的程序员面试网址
    [转]浅谈协方差矩阵
    坚持
    matlab中文论坛
    看书
    Opengl绘制点
    说服力
    心情
    vector操作
    我的毕设
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798567.html
Copyright © 2011-2022 走看看