POJ 3241 Object Clustering 曼哈顿最小生成树
Description
We have N (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 (a, b ≤ 500). The resemblance of object i and object j is defined by dij = |ai - aj| + |bi - 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 N objects into K (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
整个题:就是求manhattan最小生成树
曼哈顿距离最小生成树问题可以简述如下:
给定二维平面上的N个点,在两点之间连边的代价为其曼哈顿距离,求使所有点连通的最小代价。
朴素的算法可以用O(N2)的Prim,或者处理出所有边做Kruskal,但在这里总边数有O(N2)条,所以Kruskal的复杂度变成了O(N2logN)。
但是事实上,真正有用的边远没有O(N2)条。我们考虑每个点会和其他一些什么样的点连边。可以得出这样一个结论,以一个点为原点建立直角坐标系,在每45度内只会向距离该点最近的一个点连边。
这个结论可以证明如下:假设我们以点A为原点建系,考虑在y轴向右45度区域内的任意两点B(x1,y1)和C(x2,y2),不妨设|AB|≤|AC|(这里的距离为曼哈顿距离),如下图:
|AB|=x1+y1,|AC|=x2+y2,|BC|=|x1-x2|+|y1-y2|。而由于B和C都在y轴向右45度的区域内,有y-x>0且x>0。下面我们分情况讨论:
1. x1>x2且y1>y2。这与|AB|≤|AC|矛盾;
2. x1≤x2且y1>y2。此时|BC|=x2-x1+y1-y2,|AC|-|BC|=x2+y2-x2+x1-y1+y2=x1-y1+2*y2。由前面各种关系可得y1>y2>x2>x1。假设|AC|<|BC|即y1>2*y2+x1,那么|AB|=x1+y1>2*x1+2*y2,|AC|=x2+y2<2*y2<|AB|与前提矛盾,故|AC|≥|BC|;
3. x1>x2且y1≤y2。与2同理;
4. x1≤x2且y1≤y2。此时显然有|AB|+|BC|=|AC|,即有|AC|>|BC|。
综上有|AC|≥|BC|,也即在这个区域内只需选择距离A最近的点向A连边。
这种连边方式可以保证边数是O(N)的,那么如果能高效处理出这些边,就可以用Kruskal在O(NlogN)的时间内解决问题。下面我们就考虑怎样高效处理边。
我们只需考虑在一块区域内的点,其他区域内的点可以通过坐标变换“移动”到这个区域内。为了方便处理,我们考虑在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)。
至于坐标变换,一个比较好处理的方法是第一次直接做;第二次沿直线y=x翻转,即交换x和y坐标;第三次沿直线x=0翻转,即将x坐标取相反数;第四次再沿直线y=x翻转。注意只需要做4次,因为边是双向的。
至此,整个问题就可以在O(NlogN)的复杂度内解决了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include<vector>
#include <algorithm>
using namespace std;
const int N = 1e4+, M = 4e4+, mod = 1e9+, inf = 0x3f3f3f3f;
typedef long long ll; struct ss{
int u,v,w;
bool operator < (const ss &b) const
{
return w < b.w;
}
}e[N * ];
int tot = ,id[N] , mi[N] , pos[N] , x[N], cnt , y[N], san[N], fa[N], n ,k;
bool cmp(int i,int j)
{
if(x[i] != x[j]) return x[i] < x[j];
else return y[i] < y[j];
}
void add(int u,int v,int w) {
++tot;
e[tot].u = u, e[tot].v = v, e[tot].w = w;
}
int query(int x) {
int ret = -, ans = inf;
for(int i = x; i <= cnt; i += i&(-i)) {
if(mi[i] < ans) ans = mi[i] , ret = pos[i];
}
return ret;
}
void update(int x, int c, int p) {
for(int i = x; i >= ; i -= i&(-i)) if(mi[i] > c) mi[i] = c, pos[i] = p;
} int haxi(int x) {return lower_bound(san + , san + cnt + , x) - san;}
int dis(int i,int j)
{
return abs(x[i] - x[j]) + abs(y[i] - y[j]);
}
void Manst() {
tot = ;
for(int dir = ; dir < ; ++dir) {
if(dir == || dir == )
for(int i = ; i <= n; ++i) swap(x[i],y[i]);
else
for(int i = ; i <= n; ++i) x[i] = -x[i];
for(int i = ; i <= n; ++i) id[i] = i;
sort(id + , id + n + , cmp);
cnt = ;
for(int i = ; i <= n; ++i) san[++cnt] = y[i] - x[i];
sort(san + , san + cnt + );
cnt = unique(san + , san + cnt + ) - san - ;
for(int i = ; i <= n; ++i) mi[i] = inf , pos[i] = -;
for(int i = n; i >= ; --i) {
int u = haxi(y[id[i]] - x[id[i]]);
int v = query(u);
if(v != -) add(id[i], v, dis(id[i], v));
update(u, x[id[i]] + y[id[i]], id[i]);
}
}
} int finds(int x) {return x==fa[x]?x:fa[x]=finds(fa[x]);} int main()
{
while(~scanf("%d%d",&n,&k)) { for(int i=;i<=n;i++) scanf("%d%d",&x[i],&y[i]); Manst();
sort(e + , e+ tot + );
for(int i = ; i <= n; ++i) fa[i] = i;
k = n - k;
for(int i = ; i <= tot; ++i)
{
int u = e[i].u, v = e[i].v, c = e[i].w;
if(finds(u) != finds(v)) {
--k;
fa[finds(u)] = finds(v);
if(k == ) {
printf("%d\n",c);
break;
}
}
}
}
}
POJ 3241 Object Clustering 曼哈顿最小生成树的更多相关文章
- poj 3241 Object Clustering (曼哈顿最小生成树)
Object Clustering Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 2640 Accepted: 806 ...
- POJ3241 Object Clustering 曼哈顿最小生成树
题意:转换一下就是求曼哈顿最小生成树的第n-k条边 参考:莫涛大神的论文<平面点曼哈顿最小生成树> /* Problem: 3241 User: 96655 Memory: 920K Ti ...
- POJ 3241 Object Clustering(Manhattan MST)
题目链接:http://poj.org/problem?id=3241 Description We have N (N ≤ 10000) objects, and wish to classify ...
- 【POJ 3241】Object Clustering 曼哈顿距离最小生成树
http://poj.org/problem?id=3241 曼哈顿距离最小生成树模板题. 核心思想是把坐标系转3次,以及以横坐标为第一关键字,纵坐标为第二关键字排序后,从后往前扫.扫完一个点就把它插 ...
- POJ3241 Object Clustering(最小生成树)题解
题意:求最小生成树第K大的边权值 思路: 如果暴力加边再用Kruskal,边太多会超时.这里用一个算法来减少有效边的加入. 边权值为点间曼哈顿距离,那么每个点的有效加边选择应该是和他最近的4个象限方向 ...
- POJ 3241Object Clustering曼哈顿距离最小生成树
Object Clustering Description We have N (N ≤ 10000) objects, and wish to classify them into several ...
- 【Poj3241】Object Clustering
Position: http://poj.org/problem?id=3241 List Poj3241 Object Clustering List Description Knowledge S ...
- 【poj3241】 Object Clustering
http://poj.org/problem?id=3241 (题目链接) MD被坑了,看到博客里面说莫队要写曼哈顿最小生成树,我就写了一个下午..结果根本没什么关系.不过还是把博客写了吧. 转自:h ...
- 【BZOJ-2177】曼哈顿最小生成树 Kruskal + 树状数组
2177: 曼哈顿最小生成树 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 190 Solved: 77[Submit][Status][Discu ...
随机推荐
- 从其它系统登录到SharePoint 2010系统的单点登录
以前做的只是使用SharePoint的单一登录,用SharePoint去登录其他的系统,现在要反过来,用Form认证的系统来登录SharePoint. 我们都知道,SharePoint使用的是域认证系 ...
- 【leetcode】Excel Sheet Column Title
Excel Sheet Column Title Given a non-zero positive integer, return its corresponding column title as ...
- IDEA 编译时报错 “未结束的字符串文字” “解析时已经达到文件结尾”
Information:Using javac 1.7.0_75 to compile java sourcesInformation:java: Errors occurred while comp ...
- 设定报表变量的CharSpacing
设定报表变量的CharSpacing字符间距,预览时都没问题, 间距大的字与字之间拉得比较大,但在大多数电脑打印时和预览的结果一样,但有些电脑打印出来却跟没有设间距一样?
- drupal记录(一)
翻译包下载网址:locallize.drupal.org 中文模块 local 自动下载模块 L10n_update 第三方menu菜单 admin menu,menu bar 打开这个后要关闭系统自 ...
- Effective C++ -----条款18:让接口容易被正确使用,不易被误用
好的接口很容易被正确使用,不容易被误用.你应该在你IDE所有接口中努力达成这些性质. “促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容. “阻止误用"的办法包括建立新类型.限 ...
- 用Mybatis返回Map,List<Map>
返回Map,Mybatis配置如下 : <select id="getCountyHashMap" resultType="java.util.HashMap&qu ...
- 【leetcode】Minimum Window Substring (hard) ★
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
- 浏览器方法及代码打包成APP的
<script src=" http://static.ydbimg.com/API/YdbOnline.js" type="text/javascript&quo ...
- PHP中的常用魔术方法
魔术方法: 是指某些情况下,会自动调用的方法,称为魔术方法 php面向对象中,提供了这几个魔术方法,他们的特点都是 以双下划线__开头的 __construct() 构造方法 __destruct( ...