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

Description

We have (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 (ab ≤ 500). The resemblance of object i and object j is defined by dij = |a- aj| + |b- 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 Nobjects into 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

题目大意:

(在平面坐标第一象限)给你n个整点,A(x1,y1)和B(x2,y2)两点之间的距离定义为|x1-x2|+|y1-y2|,求最小生成树第k大边。

曼哈顿最小生成树经典题。

首先这道题条件给的不充分啊:点都在第一象限(不包括坐标轴),没有重(chong)点。

大致理一下思路:

首先,如果将点两两相连,边数是O(n^2)的。但并非所有的边都有用。网上有很多相关的证明,可以证得,只需对一二象限均分的四个部分分别求最近的点加边。

其次,怎么处理呢。先考虑y轴左偏45度的那一块。先对y-x离散化,再对x排序(排序函数要注意,因为要把边界算上),这样每次查询y-x和x比当前点大的点中最小值就好了(用线段树)。这一块实现起来确实比较麻烦,详见代码。

再次,其余三个部分通过坐标变换就可以套用第一部分的处理方式了。(x,y)(y,x)(-y,x)(x,-y)。

最后,跑个kruskal就ok了。

#include<cstdio>
#include<algorithm> using namespace std; const int maxn=;
const int inf=; struct tdot
{
int x,y;
int num;//每个点的序号
int dis;//离散化后的值
};
tdot dot[maxn+]; //x
int cmp1(tdot a,tdot b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x<b.x;
} //y-x
int cmp2(tdot a,tdot b)
{
if(a.y-a.x==b.y-b.x)
return a.x<b.x;
return a.y-a.x<b.y-b.x;
} //离散化及预处理
void discrete(int n)
{
sort(dot+,dot+n+,cmp2);
for(int i=;i<=n;i++)
dot[i].dis=i;
sort(dot+,dot+n+,cmp1);
} struct ttree
{
int l,r;
int num;
int mmin;
};
ttree tree[maxn*+]; void pushup(int x)
{
if(tree[x].l==tree[x].r)
return;
if(tree[x*].mmin<=tree[x*+].mmin)
tree[x].mmin=tree[x*].mmin,tree[x].num=tree[x*].num;
else
tree[x].mmin=tree[x*+].mmin,tree[x].num=tree[x*+].num;
} void build(int x,int l,int r)
{
tree[x].l=l;tree[x].r=r;
tree[x].mmin=inf;
tree[x].num=;
if(l<r)
{
int mid=(l+r)/;
build(x*,l,mid);
build(x*+,mid+,r);
}
} void modify(int x,int pos,int mmin,int num)
{
if(tree[x].l==tree[x].r)
tree[x].mmin=mmin,tree[x].num=num;
else
{
int mid=(tree[x].l+tree[x].r)/;
if(pos<=mid)
modify(x*,pos,mmin,num);
else
modify(x*+,pos,mmin,num);
pushup(x);
}
} struct tret
{
int mmin,num;
}; tret query(int x,int l,int r)
{
tret ret;
ret.mmin=inf;ret.num=;
if(l<=tree[x].l&&r>=tree[x].r)
{
ret.mmin=tree[x].mmin;
ret.num=tree[x].num;
return ret;
}
int mid=(tree[x].l+tree[x].r)/;
if(l<=mid)
{
tret ret0=query(x*,l,r);
if(ret.mmin>ret0.mmin)
ret.mmin=ret0.mmin,ret.num=ret0.num;
}
if(r>mid)
{
tret ret0=query(x*+,l,r);
if(ret.mmin>ret0.mmin)
ret.mmin=ret0.mmin,ret.num=ret0.num;
}
return ret;
} struct tedge
{
int a,b;
int w;
};
tedge edge[maxn*+];
int cnt=; //加边
void addedge(int n)
{
build(,,n);
for(int i=n;i>=;i--)
{
tret ret=query(,dot[i].dis,n);
if(ret.num!=)
{
edge[cnt].a=dot[i].num;
edge[cnt].b=ret.num;
edge[cnt++].w=ret.mmin-dot[i].x-dot[i].y;
}
modify(,dot[i].dis,dot[i].x+dot[i].y,dot[i].num);
}
} //kruskal用比较函数
int cmp(tedge a,tedge b)
{
return a.w<b.w;
} int fa[maxn+]; int father(int x)
{
if(fa[x]==x)
return x;
return fa[x]=father(fa[x]);
} int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
scanf("%d%d",&dot[i].x,&dot[i].y);
dot[i].num=i;
} discrete(n);
addedge(n); for(int i=;i<=n;i++)
swap(dot[i].x,dot[i].y);
discrete(n);
addedge(n); for(int i=;i<=n;i++)
dot[i].x*=-;
discrete(n);
addedge(n); for(int i=;i<=n;i++)
swap(dot[i].x,dot[i].y);
discrete(n);
addedge(n); //kruskal
for(int i=;i<=n;i++)
fa[i]=i;
sort(edge+,edge+cnt,cmp);
for(int i=,j=;i<cnt;i++)
{
int fx=father(edge[i].a);
int fy=father(edge[i].b);
if(fx!=fy)
{
fa[fx]=fy;
j++;
}
if(j==n-k)
{
printf("%d\n",edge[i].w);
break;
}
} return ;
}

PS:看别人的解题报告只是一种学习的途径。代码的实现还是要靠自己写。这两者的深度是大不相同的,有些东西只有在自己写代码的时候才能体会到。这道题前前后后写了三遍,终于过了,开心。

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. POJ3241 Object Clustering 曼哈顿最小生成树

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

  3. POJ 3241 Object Clustering(Manhattan MST)

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

  4. 【POJ 3241】Object Clustering 曼哈顿距离最小生成树

    http://poj.org/problem?id=3241 曼哈顿距离最小生成树模板题. 核心思想是把坐标系转3次,以及以横坐标为第一关键字,纵坐标为第二关键字排序后,从后往前扫.扫完一个点就把它插 ...

  5. POJ3241 Object Clustering(最小生成树)题解

    题意:求最小生成树第K大的边权值 思路: 如果暴力加边再用Kruskal,边太多会超时.这里用一个算法来减少有效边的加入. 边权值为点间曼哈顿距离,那么每个点的有效加边选择应该是和他最近的4个象限方向 ...

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

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

  7. 【Poj3241】Object Clustering

    Position: http://poj.org/problem?id=3241 List Poj3241 Object Clustering List Description Knowledge S ...

  8. 【poj3241】 Object Clustering

    http://poj.org/problem?id=3241 (题目链接) MD被坑了,看到博客里面说莫队要写曼哈顿最小生成树,我就写了一个下午..结果根本没什么关系.不过还是把博客写了吧. 转自:h ...

  9. 【BZOJ-2177】曼哈顿最小生成树 Kruskal + 树状数组

    2177: 曼哈顿最小生成树 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 190  Solved: 77[Submit][Status][Discu ...

随机推荐

  1. electron——dialog(实现导出excel)

    背景 前端点击导出excel按钮后,请求完需要导出的数据后发送给主进程electron,由主进程保存到本地 dialog 显示用于打开和保存文件.警报等的本机系统对话框. dialog 模块提供了ap ...

  2. (四十二)golang--管道

    假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ...

  3. URL基本语法

    1.URL全称为Uniform Resource Locator,即统一资源定位符.对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一 ...

  4. Java 从入门到进阶之路(九)

    之前的文章我们介绍了一下 Java 中的构造方法,接下来我们再来看一下 Java 中的引用型数组类型. 现在我们想定义一个坐标系,然后通过横坐标(row)和纵坐标(col)来确定一个坐标点,代码如下: ...

  5. python模块2

    python模块2 相关概念 模块名是标识符(需要按照标识符的写法编写) Pyc文件 在使用模块的项目中会生成一个_pycache_文件,里面存放着编译过的(模块的)字节码缓存文件(因为模块一般很少有 ...

  6. mac安装numpy,scipy,matplotlib

      SaintKings-Mac-mini:~ saintking$ python Python ( , ::) [GCC Compatible Apple LLVM (clang-)] on dar ...

  7. #化鲲为鹏,我有话说# 鲲鹏弹性云服务器配置 Tomcat

    在鲲鹏弹性云服务器上配置 Tomcat 1 下载 Tomcat 地址 :http://tomcat.apache.org/ 根据需要选择版本,这里使用 Tomcat 9,下载压缩包 2 将文件发送到服 ...

  8. CAS都不了解,你还怎么看J.U.C

    前言 说到CAS(CompareAndSwap),不得不先说一说悲观锁和乐观锁,因为CAS是乐观锁思想的一种实现. 悲观锁:总是很悲观的认为,每次拿数据都会有其他线程并发执行,所以每次都会进行加锁,用 ...

  9. Swift语法注意

    一直没有太弄明白可选值以及解包.下面说一下几点理解: OC中与Swift的nil 的区别: OC中nil表示指向不存在对象的指针 swift中表示值不存在,任何类型的可选值都可以为nil,包含基本数据 ...

  10. iOS 自定义TabBarController

    转自:http://blog.csdn.net/xn4545945/article/details/35994863 一.自定义的思路 iOS中的TabBarController确实已经很强大了,大部 ...