POJ-3241-Object Clustering
2016-06-09 20:00
477 查看
ACM模版
曼哈顿最小生成树
POJ 3241 Object Clustering曼哈顿距离
简单说,他指两点之间的横纵坐标的差的绝对值之和。
题意
查找平面上的点的曼哈顿距离最小生成树的第n-k小边的长度,点数在100000以内。
解析
对于曼哈顿距离的最小生成树,朴素算法需要建立n^(n - 1)条边进行kruskal算法处理,这样子做一定会TLE的。所以需要做特殊的优化,将边数优化为4 * n条。 这里的优化涉及到一个与曼哈顿相关的性质:以任一一个点为端点,将平面分为八块,每块占45度角,那么在生成树的最优解中,每个块与这个点至多有一条边,即一个点最多分别向八个方向最近的点连接一条边,一条边两个点共用,所以最后边数为4 * n。
代码C++
#include <iostream> #include <algorithm> const int MAXN = 100010; const int INF = 0x3f3f3f3f; struct Point { int x; int y; int id; }poi[MAXN]; bool cmp(Point a, Point b) { if (a.x != b.x) { return a.x < b.x; } else { return a.y < b.y; } } //树状数组,找y - x大于当前的,但是y + x最小的 struct BIT { int minVal; int pos; void init() { minVal = INF; pos = -1; } }bit[MAXN]; //所有有效边 struct Edge { int u; int v; int d; }edge[MAXN << 2]; bool cmpEdge(Edge a, Edge b) { return a.d < b.d; } int tot; int n; int F[MAXN]; int find(int x) { if (F[x] == -1) { return x; } else { return F[x] = find(F[x]); } } void addEdge(int u, int v, int d) { edge[tot].u = u; edge[tot].v = v; edge[tot++].d = d; return ; } int lowbit(int x) { return x & (-x); //??? } //更新bit void update(int i, int val, int pos) { while (i > 0) { if (val < bit[i].minVal) { bit[i].minVal = val; bit[i].pos = pos; } i -= lowbit(i); } return ; } //查询[i, m]的最小值位置 int ask(int i, int m) { int minVal = INF; int pos = -1; while (i <= m) { if (bit[i].minVal < minVal) { minVal = bit[i].minVal; pos = bit[i].pos; } i += lowbit(i); } return pos; } int dist(Point a, Point b) { return abs(a.x - b.x) + abs(a.y - b.y); } void ManhattanMinimumSpanningTree(int n, Point p[]) { int a[MAXN], b[MAXN]; tot = 0; for (int dir = 0; dir < 4; dir++) { //变换4种坐标 if (dir == 1 || dir == 3) { for (int i = 0; i < n; i++) { std::swap(p[i].x, p[i].y); } } else if (dir == 2) { for (int i = 0; i < n; i++) { p[i].x = -p[i].x; } } std::sort(p, p + n, cmp); for (int i = 0; i < n; i++) { a[i] = b[i] = p[i].y - p[i].x; } std::sort(b, b + n); int m = (int)(std::unique(b, b + n) - b); for (int i = 1; i <= m; i++) { bit[i].init(); } for (int i = n - 1; i >= 0; i--) { int pos = (int)(std::lower_bound(b, b + m, a[i]) - b + 1); int ans = ask(pos, m); if (ans != -1) { addEdge(p[i].id, p[ans].id, dist(p[i], p[ans])); } update(pos, p[i].x + p[i].y, i); } } return ; } int solve(int k) { ManhattanMinimumSpanningTree(n, poi); memset(F, -1, sizeof(F)); std::sort(edge, edge + tot, cmpEdge); for (int i = 0; i < tot; i++) { int u = edge[i].u; int v = edge[i].v; int tOne = find(u); int tTwo = find(v); if (tOne != tTwo) { F[tOne] = tTwo; k--; if (k == 0) { return edge[i].d; } } } return -1; } int main(int argc, const char * argv[]) { //freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); int k; while ((std::cin >> n >> k) && n) { for (int i = 0; i < n; i++) { std::cin >> poi[i].x >> poi[i].y; poi[i].id = i; } std::cout << solve(n - k) << std::endl; } return 0; }
相关文章推荐
- POJ 3241 Object Clustering
- iOS开发之Objective-C与JavaScript的交互 ——stringByEvaluatingJavaScriptFromString
- toString(),String.ValueOf,(String)Object的区别
- Objective C类方法load和initialize的区别
- Gradle sync failed: Cannot locate factory for objects of type DefaultGradleConnector, as ConnectorSe
- CObject::Dump(CDumpContext& dc )函数的学习
- objective-c --单知识点运用---FMDatabase -- -数据库操作
- python3 报错: AttributeError: 'module' object has no attribute 'urlopen'
- 为什么在 Objective-C 中给 nil 发送消息程序不会崩溃?
- 一、Object对象
- Objective-C 的“多继承”
- Objective C 和 Javascript 之间的互相调用
- sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
- Fast R-CNN: Fast Region-based Convolutional Networks for object detection
- Core Foundation对象转化为Objectctive-C对象
- js 中object对象转json
- JSONObject的简单例子
- [javaSE] 面向对象(Object类toString)
- ABAP程序中Data object的可见性
- ObjectArx 相关博客地址【更新中】