BZOJ 2177 [曼哈顿最小生成树]
来源:互联网 发布:mac 强制清理垃圾桶 编辑:程序博客网 时间:2024/04/30 20:13
Description
平面坐标系
xOy 内,给定n 个顶点V=(x,y) 。对于顶点u,v,u 与v 之间的距离d 定义为|xu–xv|+|yu–yv| 。你的任务就是求出这n 个顶点的最小生成树。
Solution
把平面划分为八个区域以后只有这八个区域的最近点与该点的连边在
找到这八个点只要用树状数组维护一下即可。
好像很妙的方法。
有一个地方要去重,不然会WA
#include <cstdio>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;const int N = 101010;const int INF = 2147483647;inline char get(void) { static char buf[100000], *S = buf, *T = buf; if (S == T) { T = (S = buf) + fread(buf, 1, 100000, stdin); if (S == T) return EOF; } return *S++;}inline void read(int &x) { static char c; x = 0; int sgn = 0; for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1; for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0'; if (sgn) x = -x;}struct Point { int x, y, id; Point (int _x = 0, int _y = 0, int i = 0):x(_x), y(_y), id(i) {} inline friend bool operator <(const Point &a, const Point &b) { return a.x == b.x ? a.y < b.y : a.x < b.x; } inline void Ref(int dir) { if (dir & 1) swap(x, y); else if (dir == 2) x = -x; }};struct node { int pos, key; node (int p = 0, int k = 0):pos(p), key(k) {}};struct edge { int from, to, key; edge(int f = 0, int t = 0, int k = 0):from(f), to(t), key(k) {} inline friend bool operator <(const edge &a, const edge &b) { return a.key < b.key; }};node C[N];Point P[N];edge G[N << 3];int n, pos, Gcnt, cnt;long long ans;int mp[N], v[N];int fa[N], rk[N];inline int lowbit(int x) { return x & -x;}inline void Modify(int x, int key, int pos) { for (; x; x -= lowbit(x)) if (C[x].key > key) C[x] = node(pos, key);}inline int Query(int x) { int key = INF, pos = -1; for (; x <= n; x += lowbit(x)) if (C[x].key < key) { key = C[x].key; pos = C[x].pos; } return pos;}inline int Abs(int x) { return x < 0 ? -x : x;}inline int Dis(const Point &a, const Point &b) { return Abs(a.x - b.x) + Abs(a.y - b.y);}inline int F(int x) { return fa[x] == x ? x : fa[x] = F(fa[x]);}inline bool Merge(int x, int y) { static int f1, f2; f1 = F(x); f2 = F(y); if (f1 == f2) return false; if (rk[f1] > rk[f2]) swap(f1, f2); if (rk[f1] == rk[f2]) rk[f2]++; fa[f1] = f2; return true;}inline bool cmp(const int a, const int b) { return v[a] < v[b];}inline void AddEdge(int from, int to, int key) { G[++Gcnt] = edge(from, to, key);}int main(void) { freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); read(n); for (int i = 1; i <= n; i++) { read(P[i].x); read(P[i].y); P[i].id = i; fa[i] = i; } for (int dir = 0; dir < 4; dir++) { for (int i = 1; i <= n; i++) P[i].Ref(dir); sort(P + 1, P + n + 1); for (int i = 1; i <= n; i++) { mp[i] = i; v[i] = P[i].y - P[i].x; C[i] = node(-1, INF); } sort(mp + 1, mp + n + 1, cmp); cnt = 0; mp[n + 1] = INF; for (int i = 1; i <= n; i++) { ++cnt; while (v[mp[i]] == v[mp[i + 1]]) v[mp[i++]] = cnt; v[mp[i]] = cnt; } // 离散去重 for (int i = n; i; i--) { pos = Query(v[i]); if (~pos) AddEdge(P[i].id, P[pos].id, Dis(P[i], P[pos])); Modify(v[i], P[i].x + P[i].y, i); } } sort(G + 1, G + Gcnt + 1); for (int i = 1; i <= Gcnt; i++) { if (Merge(G[i].from, G[i].to)) { n--; ans += G[i].key; if (n == 1) break; } } cout << ans << endl;}
0 0
- BZOJ 2177 [曼哈顿最小生成树]
- BZOJ 2177 最小曼哈顿生成树
- 曼哈顿最小生成树
- 平面曼哈顿最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- poj3241 曼哈顿最小生成树
- 二维曼哈顿最小生成树
- UVALA 3662 曼哈顿最小生成树
- POJ 3241 曼哈顿最小生成树
- 曼哈顿最小生成树&&莫队算法
- kattis Grid MST (最小曼哈顿生成树)
- [BZOJ2177][最小/最大(曼哈顿距离)生成树]曼哈顿最小生成树
- 关于曼哈顿距离下的最小生成树
- poj 3241 Object Clustering(曼哈顿最小生成树)
- 曼哈顿距离最小生成树与莫队算法
- POJ 3241 Object Clustering (曼哈顿距离最小生成树)
- 【codevs1287】矩阵乘法(矩阵乘法)
- Jquery之动画(四)
- 采用Retrofit的PUT方式上传文件到apache
- 《Java高并发程序设计》学习 --3.2 线程复用:线程池
- 自己总结的QT相关资料和网址汇总
- BZOJ 2177 [曼哈顿最小生成树]
- hihoCoder 1478 水陆距离
- IE浏览器下的JS鼠标特效(文本跟随鼠标环绕的特效)
- 安卓开发之WebView控件只用
- Spark磁盘空间满了
- Ngrok穿透工具的使用
- 世界上主流的五大浏览器及其内核
- highcharts图表:如何配置坐标轴数据过大是否折算进行单位(k,M,G,T,P,E)替换
- poj 2976 && poj 2728 && poj3621 && bzoj 1486 01分数规划