http://poj.org/problem?id=3241

曼哈顿距离最小生成树模板题。

核心思想是把坐标系转3次,以及以横坐标为第一关键字,纵坐标为第二关键字排序后,从后往前扫。扫完一个点就把它插到树状数组的y-x位置上,权值为x+y。查询时查询扫过的所有点满足ydone-xdone>=ynow-xnow时,直接是树状数组中的的一个后缀区间,从后往前扫保证了区间内的这些点都在当前点的y轴向右扫45度的范围内。树状数组实现查询x+y的最小值,以及此最小值对应原数组中的位置,方便建图连边。

模板是抄的别人的QAQ

时间复杂度$O(n\log n)$

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100003;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct Point {
int x, y, id;
bool operator < (const Point &A) const {
return x == A.x ? y < A.y : x < A.x;
}
} P[N];
struct Bits {
int mn, pos;
void init() {mn = 0x7fffffff; pos = -1;}
} bit[N];
int tot;
struct Edge {
int u, v, dis;
bool operator < (const Edge &A) const {
return dis < A.dis;
}
} E[N << 2];
void add(int a, int b, int c) {E[++tot] = (Edge) {a, b, c};} int n, fa[N], k;
int find(int x) {
if (fa[x] == x) return x;
fa[x] = find(fa[x]); return fa[x];
} int dist(int x, int y) {
return abs(P[x].x - P[y].x) + abs(P[x].y - P[y].y);
} void update(int x, int num, int pos) {
for(; x; x -= (x & (-x)))
if (num < bit[x].mn)
bit[x].mn = num, bit[x].pos = pos;
} int m;
int query(int x) {
int ans = 0x7fffffff, pos = -1;
for(x; x <= m; x += (x & (-x)))
if (bit[x].mn < ans)
ans = bit[x].mn, pos = bit[x].pos;
return pos;
} int a[N], H[N], cnt;
int solve() {
for(int change = 0; change < 4; ++change) {
if (change == 1 || change == 3)
for(int i = 1; i <= n; ++i) swap(P[i].x, P[i].y);
else if (change == 2)
for(int i = 1; i <= n; ++i) P[i].x = -P[i].x; sort(P + 1, P + n + 1);
for(int i = 1; i <= n; ++i)
a[i] = H[i] = P[i].y - P[i].x;
cnt = n;
sort(H + 1, H + cnt + 1);
cnt = unique(H + 1, H + cnt + 1) - H;
for(int i = 1; i <= cnt; ++i) bit[i].init();
int pos, tmp; m = cnt;
for(int i = n; i > 0; --i) {
pos = lower_bound(H + 1, H + cnt, a[i]) - H;
tmp = query(pos);
if (tmp != -1)
add(P[i].id, P[tmp].id, dist(i, tmp));
update(pos, P[i].x + P[i].y, i);
}
}
sort(E + 1, E + tot + 1);
cnt = n - k;
for(int i = 1; i <= n; ++i) fa[i] = i;
int u, v;
for(int i = 1; i <= tot; ++i) {
u = find(E[i].u); v = find(E[i].v);
if (u != v) {
--cnt;
fa[u] = v;
if (cnt == 0) return E[i].dis;
}
}
} int main() {
while (~scanf("%d%d", &n, &k)) {
tot = 0;
for(int i = 1; i <= n; ++i) {
P[i].x = in(); P[i].y = in();
P[i].id = i;
}
printf("%d\n", solve());
}
return 0;
}

【POJ 3241】Object Clustering 曼哈顿距离最小生成树的更多相关文章

  1. POJ 3241 Object Clustering 曼哈顿最小生成树

    Object Clustering   Description We have N (N ≤ 10000) objects, and wish to classify them into severa ...

  2. poj 3241 Object Clustering (曼哈顿最小生成树)

    Object Clustering Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 2640   Accepted: 806 ...

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

    Object Clustering Description We have N (N ≤ 10000) objects, and wish to classify them into several ...

  4. POJ 3241 Object Clustering(Manhattan MST)

    题目链接:http://poj.org/problem?id=3241 Description We have N (N ≤ 10000) objects, and wish to classify ...

  5. 51nod 1213 二维曼哈顿距离最小生成树

    1213 二维曼哈顿距离最小生成树 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间 ...

  6. 曼哈顿距离最小生成树 codechef Dragonstone

    曼哈顿距离最小生成树 codechef Dragonstone 首先,对于每一个点来说有用的边只有它向它通过 x=0,y=0,y=x,y=-x 切出来的八个平面的最近点. 证明 我不会 反正当结论记住 ...

  7. [51nod1213]二维曼哈顿距离最小生成树

    二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间的距离为:横纵坐标的差的绝对值之和,即:Abs(x1 - x2) + Abs(y1 - y2)(也称曼哈顿距离).求这N个点所组成的完全图 ...

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

    先上几个资料: 百度文库有详细的分析和证明 cxlove的博客 TopCoder Algorithm Tutorials #include <cstdio> #include <cs ...

  9. POJ3241 Object Clustering 曼哈顿最小生成树

    题意:转换一下就是求曼哈顿最小生成树的第n-k条边 参考:莫涛大神的论文<平面点曼哈顿最小生成树> /* Problem: 3241 User: 96655 Memory: 920K Ti ...

随机推荐

  1. win10 右键菜单添加使用gvim打开方式

    ①打开注册表编辑器,开始-->运行-->regedit ②定位到:HKEY_CLASSSES_ROOT---> * --->Shell,在Shell 上右击,新建---> ...

  2. AC日记——画矩形 1.5 42

    42:画矩形 总时间限制:  1000ms 内存限制:  65536kB 描述 根据参数,画出矩形. 输入 输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于3行不多于10行,宽 ...

  3. 【Unity】矩阵运算

    http://www.cnblogs.com/wywnet/p/3585075.html Vector3:  Unity3D中Vector3类定义(只写有用的):  属性:  x,y,z       ...

  4. 怎样使用VMware Workstation(虚拟机)

    怎样使用VMware Workstation(虚拟机) 听语音 浏览:66981 | 更新:2010-12-06 16:26 | 标签:vmware 1 2 3 4 5 6 7 分步阅读 一键约师傅 ...

  5. 嵌入式Linux驱动学习之路(五)u-boot启动流程分析

    这里说的u-boot启动流程,值得是从上电开机执行u-boot,到u-boot,到u-boot加载操作系统的过程.这一过程可以分为两个过程,各个阶段的功能如下. 第一阶段的功能: 硬件设备初始化. 加 ...

  6. maya 专家模式

    maya中按ctrl + 空格 可以在普通模式与专家模式之间切换,如图 普通模式 按ctrl+空格后进入专家模式 来自为知笔记(Wiz)

  7. 转 mvc项目中,解决引用jquery文件后智能提示失效的办法

    mvc项目中,解决用Url.Content方法引用jquery文件后智能提示失效的办法   这个标题不知道要怎么写才好, 但是希望文章的内容对大家有帮助. 场景如下: 我们在用开发开发程序的时候,经常 ...

  8. centos6下安装dedecms

    几经波折,终于安装成功!!! 一.centos6下安装WDCP 1.连接linux 在百度直接搜索下载xshell,通过ssh连接 2.安装wdcp 下载安装wget http://dl.wdlinu ...

  9. 重构Web Api程序(Api Controller和Entity)

    Insus.NET较习惯做法,是在程序完成之后,抽一些少时间对写好的代码重新审视.比如这些天写的Web Api的程序来说,发现有很多值得重构代码. 开发ASP.NET MVC程序,与数据相关有关联的一 ...

  10. Castle.ActiveRecord 多对多关系 引发的错误处理

    在Castle.ActiveRecord 实体类中,如果两个对象有 “多对多” 关系,一般的做法是将其分解为 两个“一对多”关系,但有时引发了 “您要删除 或 引用 的对象#2在数据库中不存在”的异常 ...