曼哈顿距离MST

https://www.cnblogs.com/xzxl/p/7237246.html

讲的不错

/*
曼哈顿距离最小生成树 poj 3241 Object Clustering
按照上面的假设我们先考虑y周顺时针45°的情况
dis(i,j)=x[j]-x[i]+y[j]-y[i]=x[j]+y[j]-(x[i]+x[j])
dis取决于x[j]+y[j] 所以排序的关键字就是x+y
然后我们按y-x离散化 然后维护 y-x大于当前点 的点中
x+y最小的点 时间复杂度NlogN 最大生成树的话 不具有对称性 需要往8个方向都搞一遍
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,k,m,num,s[maxn],vl[maxn],idex[maxn],a[maxn],b[maxn],fa[maxn];
struct node{
    int x,y,id;
}poi[maxn];
struct edge{
    int u,v,t;
}e[maxn*20];
int cmp1(const node &A,const node &B){
    if(A.x==B.x)return A.y<B.y;
    return A.x<B.x;
}
int cmp2(const edge &A,const edge &B){
    return A.t<B.t;
}
void Add(int u,int v,int t){
    num++;e[num].u=u;
    e[num].v=v;e[num].t=t;
}
int Abs(int x){
    return x>0?x:-x;
}
int Cal(int i,int j){
    return Abs(poi[i].x-poi[j].x)+Abs(poi[i].y-poi[j].y);
}
int find(int x){
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
void Insert(int pos,int val,int id){
    while(pos){
        if(vl[pos]>val){
            vl[pos]=val;idex[pos]=id;
        }
        pos-=(pos&-pos);
    }
}
int Query(int pos){
    int res=-1,mx=1e9+7;
    while(pos<=n){
        if(mx>vl[pos]){
            mx=vl[pos];res=idex[pos];
        }
        pos+=(pos&-pos);
    }
    return res;
}
int main(){
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&poi[i].x,&poi[i].y);
        poi[i].id=i;
    }
    for(int K=1;K<=4;K++){
        memset(vl,127/3,sizeof(vl));
        memset(idex,-1,sizeof(idex));
        if(K==2||K==4)
            for(int i=1;i<=n;i++)
                swap(poi[i].x,poi[i].y);
        else if(K==3)
            for(int i=1;i<=n;i++)
                poi[i].x=-poi[i].x;
        sort(poi+1,poi+1+n,cmp1);
        for(int i=1;i<=n;i++)// 按照y-x进行离散化
            a[i]=b[i]=poi[i].y-poi[i].x;
        sort(b+1,b+1+n);
        m=unique(b+1,b+1+n)-b-1;
        for(int i=n;i>=1;i--){
            int pos=lower_bound(b+1,b+1+m,a[i])-b;
            int res=Query(pos);
            if(res!=-1)
                Add(poi[i].id,poi[res].id,Cal(i,res));
            Insert(pos,poi[i].x+poi[i].y,i);
        }
    }
    sort(e+1,e+1+num,cmp2);
    for(int i=1;i<=n;i++)fa[i]=i;
    int cnt=n-k;
    for(int i=1;i<=num;i++){
        if(find(e[i].u)==find(e[i].v))continue;
        fa[find(e[i].u)]=find(e[i].v);
        cnt--;if(cnt==0){
            printf("%d\n",e[i].t);break;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/yanlifneg/p/9383178.html

时间: 2024-08-03 07:08:59

曼哈顿距离MST的相关文章

POJ 3241 Object Clustering 二维平面曼哈顿距离最小生成树

题目链接:点击打开链接 题意: 给定二维平面上的n个点坐标,常数k 下面n行给出坐标 求一个最小生成树,问第k大的边是多少. 任意两个点间建一条边的花费是其曼哈顿距离. 思路:转自:点击打开链接 一.曼哈顿距离最小生成树 曼哈顿距离最小生成树问题可以简述如下: 给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价. 朴素的算法可以用O(N2)的Prim,或者处理出所有边做Kruskal,但在这里总边数有O(N2)条,所以Kruskal的复杂度变成了O(N2logN

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

题目大意:求出曼哈顿距离最小生成树上的第k大边权. 思路:首先,你要了解:http://blog.csdn.net/acm_cxlove/article/details/8890003 也就是说,我们以每一个点为中心,把平面分成8个部分,每一个部分我们只需要离这个点最近的点.然后加上建一条边连接这个边和最近的点.然后就是MST. 听说这个算法是莫队算法的基础,我现在就去学. CODE: #include <cstdio> #include <cstring> #include &l

HDU 4311&amp;4312 Meeting point-1&amp;2 (曼哈顿距离&amp;&amp;切比雪夫距离)

HDU 4311 题意:平面上有n个点,一个点(x,y)只能到达(x-1,y), (x+1,y), (x, y-1), (x, y+1)4个点.从n个点中找到一点,使其他点到此点的距离之和最小. 思路: 可以发现,两个点间距离为 |x1-x2| + |y1-y2| ,这便是两点间的曼哈顿距离. 朴素的做法是遍历所有点,枚举该点与其他点间的曼哈顿距离之和,但是会TLE: 取巧的做法是将所有点与中心点的曼哈顿距离排序,枚举中间大概250个点左右的情况比较即可(不要欺负人家数据水! 正确姿势: 用结构

HDU4312 Meeting point-2 (切比雪夫距离&amp;&amp;曼哈顿距离)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4312 题意:给定平面坐标上n(n<=100000)个点,然后在其中选一个,使得所有点到当前点的Chebyshev距离和最小. 分析: 切比雪夫距离:设a(x1,y1),b(x2,y2);DIS = max(|x1-x2|,|y1-y2|) = (|x1-x2+y1-y2|+|x1-x2-y1+y2|)/2; 我们将点aa的坐标看成(x1+y1,x1-y1),bb的坐标看成(x2+y2,x2-y2)

HDU4311 Meeting point-1(曼哈顿距离)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4311 题意: 给定n个点,选其中的一个点作为起点,然后使其他点到这个点的曼哈顿距离最小,求这个最小的距离 分析: 我们设P作为这个点作为起点 然后 ans = sum(abs|pi.x-p.x|+|pi.y-p.y| )(1<=i<=n) 我们可以对其分别按x,y进行排序,就可以去掉绝对值符号 然后化简后的公式就可以变成 设这个点在按x排完序后的位置为i; 设tot[i],表示到序号i为止的点的

BZOJ 2735: 世博会 主席树+切比雪夫距离转曼哈顿距离

2735: 世博会 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 124  Solved: 51[Submit][Status][Discuss] Description 四年一度的世博会又要举办了,Q国很荣幸成为了这次世博会的主办方.Q国主席QQ从全国各地收集了N件物品排成 一排,作为Q国馆的展出物.对于相邻摆放的一些物品,如果过于相似会让人觉得无聊,如果差别过大又会让人觉 得突兀.为了让人们对这次世博会的展出满意,QQ需要知道一些相邻物品的“

一道曼哈顿距离的数学题

藏妹子之处(excel) 试题描述 今天CZY又找到了三个妹子,有着收藏爱好的他想要找三个地方将妹子们藏起来,将一片空地抽象成一个R行C列的表格,CZY要选出3个单元格.但要满足如下的两个条件:(1)任意两个单元格都不在同一行.(2)任意两个单元格都不在同一列.选取格子存在一个花费,而这个花费是三个格子两两之间曼哈顿距离的和(如(x1,y1)和(x,y2)的曼哈顿距离为|x1-x2|+|y1-y2|).狗狗想知道的是,花费在minT到maxT之间的方案数有多少.答案模1000000007.所谓的

Codeforces 491B. New York Hotel 最远曼哈顿距离

最远曼哈顿距离有两个性质: 1: 对每个点(x,y)  分别计算  +x+y , -x+y , x-y , -x-y 然后统计每种组合的最大值就可以了, 不会对结果产生影响 2: 去掉绝对值 , 设正号为0负号为1 则 两个点的符号是可以通过异或的得到的. 如两个点 P(x,y) 和 Q(a,b) 若去掉绝对值符号后P的两个坐标为 -x +y 既对应数字 10  那么Q对应的数字则为 01 既 +a -b 两个点的曼哈顿距离为 -x +y +a -b B. New York Hotel time

【HDU 4311】Meeting point-1(前缀和求曼哈顿距离和)

题目链接 正经解法: 给定n个点的坐标,找一个点,到其他点的曼哈顿距离之和最小.n可以是100000.大概要一个O(nlogn)的算法.算欧几里得距离可以把x和y分开计算排好序后计算前缀和就可以在O(1)时间内判断一个点到其他点的距离. #include<cstdio> #include<algorithm> using namespace std; #define ll long long #define N 100005 int t,n; ll ans,sum[N],sx[N]