(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

Problem:Portal传送门

 原题目描述在最下面。

 给你n个坐标,求最小曼哈顿距离生成树。

Solution:

请一定要理解:

 有一个剪枝:把坐标分成\(8\)块,在一个\(45\)度区间内,只需要向与之距离最近的点连边。

 虽然一共有\(8\)个相对区域,但我们只需考虑\(4\)个,中心对称的不需要再连一次边。这\(4\)个区域坐标转化一下即可求解。

 先考虑每个点\(y\)轴向右的\(45\)度区域,例如,对于\(A\)点\((x0,y0)\),\(B(x1,y1)\)在\(A\)点的那部分区域内。有\(x0\leq x1,\; y0-x0\leq y1-x1\)。而\(A\)只要向满足此条件的大于\(y0-x0\)的最小\(x+y\)点连边。

 先把所有点按\(x,y\)坐标排序,从最后一个点往前处理(这样保证了\(x1>x0\)的问题),然后用树状数组维护最小的\(x+y\)。



 再来思考坐标转化的问题,把[45,90]标记为1,[0,45]标记为2,[-45,0]标记为3,[-90,-45]标记为4.

 从区域1到2,3到4只需要交换x,y坐标即可;从区域2到3只需要把x坐标去相反数即可。

AC_Code:

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define all(x) (x).begin(),(x).end()
#define mme(a,b) memset((a),(b),sizeof((a)))
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int MXN = 1e5 + 7;
const int MXE = 1e6 + 7;
const int INF = 0x3f3f3f3f;
int n, k, tot;
int ar[MXN], fa[MXN];
struct lp{
int x, y, id;
}cw[MXN], edge[MXE];
bool cmp(const lp &a, const lp &b){
if(a.x != b.x)return a.x < b.x;
return a.y < b.y;
}
bool cmp1(const lp &a, const lp &b){
return a.id < b.id;
}
//树状数组部分
struct BIT{
int w, p;
}bit[MXN];
int lowbit(int x){
return x&(-x);
}
void add(int x, int w, int p){
for(; x > 0; x -= lowbit(x)){
if(bit[x].w > w)bit[x].w = w, bit[x].p = p;
}
}
int query(int x){
int mmax = INF, p = -1;
for(; x <= n; x += lowbit(x)){
if(bit[x].w < mmax)mmax = bit[x].w, p = bit[x].p;
}
return p;
}
int Fi(int x){
return fa[x] == x? x: fa[x] = Fi(fa[x]);
}
void add_edge(int u,int v,int w){
edge[++tot].x = u;edge[tot].y = v;edge[tot].id = w;
}
int abd(int x){return (x < 0)? -x : x;}
int dist(int i, int j){
return abs(cw[i].x-cw[j].x)+abs(cw[i].y-cw[j].y);
}
void kruskal(){
sort(edge, edge + tot + 1, cmp1);
int cnt = n - k, ans;
for(int i = 0; i <= n; ++i)fa[i] = i;
for(int i = 0; i <= tot && cnt; ++i){
int pa = Fi(edge[i].x), pb = Fi(edge[i].y);
if(pa == pb)continue;
--cnt;
ans = edge[i].id;
fa[pb] = pa;
}
printf("%d\n", ans);
}
/*
我们只需考虑在一块区域内的点,其他区域内的点可以通过坐标变换“移动”到这个区域内。为了方
便处理,我们考虑在y轴向右45度的区域。在某个点A(x0,y0)的这个区域内的点B(x1,y1)满足
x1≥x0且y1-x1>y0-x0。这里对于边界我们只取一边,但是操作中两边都取也无所谓。那么
|AB|=y1-y0+x1-x0=(x1+y1)-(x0+y0)。在A的区域内距离A最近的点也即满足条件的点中
x+y最小的点。因此我们可以将所有点按x坐标排序,再按y-x离散,用线段树或者树状数组维护
大于当前点的y-x的(最小的x+y)对应的点。时间复杂度O(NlogN)。
*/
int main(int argc, char const *argv[]){
#ifndef ONLINE_JUDGE
freopen("E://ADpan//in.in", "r", stdin);
//freopen("E://ADpan//out.out", "w", stdout);
#endif
while(~scanf("%d%d", &n, &k)){
tot = -1;
for(int i = 0 ; i < n; ++i){
scanf("%d%d", &cw[i].x, &cw[i].y);
cw[i].id = i;
}
for(int dir = 1; dir <= 4; ++dir){
//坐标转换
if(dir % 2 == 0){
for(int i = 0; i < n; ++i)swap(cw[i].x, cw[i].y);
}else if(dir == 3){
for(int i = 0; i < n; ++i)cw[i].x = -cw[i].x;
}
//先x再y排序
sort(cw, cw +n, cmp);
//Discretize
for(int i = 0; i <= n; ++i){
ar[i] = cw[i].y - cw[i].x;
bit[i].w = INF; bit[i].p = -1;
}
sort(ar, ar + n);
int k = unique(ar, ar + n) - ar;
for(int i = n - 1; i >= 0; --i){
//按y-x编号
int p = lower_bound(ar, ar + k, cw[i].y - cw[i].x) - ar + 1;
int pos = query(p);//获取最小的y+x
if(pos != -1){
add_edge(cw[i].id, cw[pos].id, dist(i, pos));
}
//添加y+x
add(p, cw[i].y + cw[i].x, i);
}
}
kruskal();
}
return 0;
}

Problem Description:

POJ3241 最小曼哈顿距离生成树 - 真有趣哇的更多相关文章

  1. Hdu4311 || 4312Meeting point-1/-2 n个点中任意选一个点使得其余点到该点曼哈顿距离之和最小

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...

  2. poj3241 曼哈顿最小距离生成树第k大的边

    思路: 已知: 要生成曼哈顿距离最小生成树,一个点最多和四周8个点连线,那8个点分别是将那个点四周360度平分成8个区间,每个区间里面和那个点曼哈顿距离最小的点,所以如果有n个点,那么最多有4n条边, ...

  3. 某个点到其他点的曼哈顿距离之和最小(HDU4311)

    Meeting point-1 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. TZOJ 1689 Building A New Barn(求平面上有几个其它点求到n个点的曼哈顿距离最小)

    描述 After scrimping and saving for years, Farmer John has decided to build a new barn. He wants the b ...

  5. HDU 4311 Meeting point-1(曼哈顿距离最小)

    http://acm.hdu.edu.cn/showproblem.php?pid=4311 题意:在二维坐标中有n个点,现在要从这n个点中选出一个点,使得其他点到该点的曼哈顿距离总和最小. 思路: ...

  6. hdu 4311 & 4312 Meeting point 曼哈顿距离之和最小

    hdu 4311 题意 平面上\(n(n\leq 1e5)\)个点,找一个点到其它所有点的曼哈顿距离之和最小. 思路 如果是找一个坐标使得所有点到其曼哈顿距离之和最小,那么将\(n\)个横坐标排个序, ...

  7. 15 Puzzle (4乘4谜题) IDA*(DFS策略与曼哈顿距离启发) 的C语言实现

    大家好!这是我的第一篇博客,由于之前没有撰写博客的经验,并且也是初入计算机和人工智能领域,可能有些表述或者理解不当,还请大家多多指教. 一.撰写目的 由于这个学期在上算法与数据结构课程的时候,其中一个 ...

  8. 曼哈顿距离MST

    https://www.cnblogs.com/xzxl/p/7237246.html 讲的不错 /* 曼哈顿距离最小生成树 poj 3241 Object Clustering 按照上面的假设我们先 ...

  9. Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离

    Atitti knn实现的具体四个距离算法  欧氏距离.余弦距离.汉明距离.曼哈顿距离 1. Knn算法实质就是相似度的关系1 1.1. 文本相似度计算在信息检索.数据挖掘.机器翻译.文档复制检测等领 ...

随机推荐

  1. 【leetcode】969. Pancake Sorting

    题目如下: Given an array A, we can perform a pancake flip: We choose some positive integer k <= A.len ...

  2. Angularjs 1.3在页面中输出带Html标记的文本

    如何Angularjs1.3在页面中输出带Html标记的文本 基于安全考虑,Angularjs不允许用ng-bind或者{{}}的方法输出html文本. 在实际的应用中,比如信息管理系统,用在线编辑器 ...

  3. Win7下使用DbgPrint

    在Win7下默认DbgPrint输出信息后,使用DbgView看不到内容. 新建一个reg文件,双击导出就行了. Windows Registry Editor Version 5.00 [HKEY_ ...

  4. 拾遗:Git 常用操作回顾

    温故而知新,可以为师矣. Git 布局 工作区---->暂存区---->本地仓库---->远程仓库 Create Repository git init PATH git add P ...

  5. HTML5 placeholder实际应用经验分享及拓展

    QQ邮箱登陆(http://mail.qq.com) 如下截图啦: 我在上面一个demo类似原理上做了下修改,制作了一个这样子交互效果的demo,希望对有兴趣的同行能帮上点忙,您可以狠狠地点击这里:透 ...

  6. 绝对 "牛X" 的代码注释,喜欢就拿去用!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:Blankj https://github.com/Blankj/awesome-comment 写在前面的话:一时兴 ...

  7. 第五记 JDBC

    了解JDBC JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API(API:Application Program Inter ...

  8. JS数组 选定元素slice() slice() 方法可从已有的数组中返回选定的元素。 语法 arrayObject.slice(start,end)

    选定元素slice() slice() 方法可从已有的数组中返回选定的元素. 语法 arrayObject.slice(start,end) 参数说明: 1.返回一个新的数组,包含从 start 到 ...

  9. [LOJ#2732] 「JOISC 2016 Day 2」雇佣计划

    参考博文 (不过个人感觉我讲的稍微更清楚一点) 题目就是让我们求图中满足数值大于等于B的连通块数量 然后我们可以尝试转换为求连通块两端所产生的“谷”的数量,显然一个连通块对谷可以贡献2的答案,最终答案 ...

  10. Linux操作系统 和 Windows操作系统 的区别

    针对这两个操作系统,下面是几点区别. 1.免费与收费 在中国, windows 和 linux 都是免费的,至少对个人用户是如此,如果哪天国内windows真的严打盗版了,那linux的春天就到了!但 ...