kattis Grid MST (最小曼哈顿生成树)
来源:互联网 发布:php记录访客信息 编辑:程序博客网 时间:2024/05/17 09:18
Grid MST
This is a very simple problem. You are given
Input
The input consists of:
One line with one integer
N (1≤N≤100000 ), the number of points,N lines each with two integersx andy (0≤x,y<1000 ), the coordinates of each point.
Output
Output one line with a single integer: The weight of a Minimum Spanning Tree that spans these
40 00 11 01 1
3
50 010 010 011 112 2
14解题思路:最小曼哈顿生成树裸题,最小曼哈顿生成树难点在于建图,其实不必每个点都要与其他n - 1个点相连,每个点只需要与周围最近的八个点相连就行,这八个点分别对应于以这个点为中心的八个区域,然后我们可以通过坐标变换,变成只处理右上方45度的区域,然后 处理四个区域,也就是变换四次就行(因为要求的是最小生成树,a ->b, b->a相同的效果),然后具体处理是用树状数组或者线段树按y - x离散,维护一个x + y的最小值就行。
线段树:
#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 100000 + 10;LL inf = 1e18;int n;int tot;int father[maxn];struct point{ int x, y, id; bool operator <(const point &res) const { if(x == res.x) return y < res.y; else return x < res.x; }} Point[maxn<<4];struct edge{ int u, v; LL w; bool operator <(const edge &res) const { return w < res.w; }} Edge[maxn<<10];struct node{ int l, r, id; LL Min;} Node[maxn<<6];void add(int u, int v, LL w){ Edge[++tot].u = u; Edge[tot].v = v; Edge[tot].w = w;}void Pushup(int i){ int lson = i<<1; int rson = lson|1; if(Node[lson].Min <= Node[rson].Min) { Node[i].Min = Node[lson].Min; Node[i].id = Node[lson].id; } else { Node[i].Min = Node[rson].Min; Node[i].id = Node[rson].id; }}void build(int i, int l, int r){ Node[i].l = l; Node[i].r = r; Node[i].Min = inf; Node[i].id = -1; if(l == r) return; int f = i; int mid = (l + r)>>1; i <<= 1; build(i, l, mid); build(i|1, mid + 1, r); //Pushup(f);}void update(int i, int loc, LL value, int id){ if(Node[i].l == Node[i].r) { if(value >= Node[i].Min) return; Node[i].Min = value; Node[i].id = id; return; } int f = i; i <<= 1; if(loc <= Node[i].r) update(i, loc, value, id); else update(i|1, loc, value, id); Pushup(f);}pair<LL, int> query(int i, int l, int r){ if(Node[i].l == l && Node[i].r == r) { return make_pair(Node[i].Min, Node[i].id); } i <<= 1; if(r <= Node[i].r) return query(i, l, r); else if(l >= Node[i|1].l) return query(i|1, l, r); else { pair<LL, int> pp1 = query(i, l, Node[i].r); pair<LL, int> pp2 = query(i|1, Node[i|1].l, r); if(pp1.first <= pp2.first) return pp1; else return pp2; }}void Tran(int type){ if(type == 1) { sort(Point + 1, Point + n + 1); return; } else if(type == 2 || type == 4) { for(int i = 1; i <= n; i++) { swap(Point[i].x, Point[i].y); } sort(Point + 1, Point + n + 1); return; } else if(type == 3) { for(int i = 1; i <= n; i++) { Point[i].x = -Point[i].x; } sort(Point + 1, Point + n + 1); return; }}void getGraph(){ for(int i = 1; i <= 4; i++) { Tran(i); build(1, 0, 4000); for(int j = n; j >= 1; j--) { int loc = Point[j].y - Point[j].x; loc += 2000; pair<LL, int> pp = query(1, loc, 4000); if(pp.first < inf) { int id = pp.second; add(Point[j].id, id, pp.first - LL(Point[j].x + Point[j].y)); } update(1, loc, (LL)(Point[j].x + Point[j].y), Point[j].id); } }}void init(){ tot = 0; for(int i = 1; i <= n; i++) father[i] = i;}int Find(int x){ if(father[x] == x) return x; else return father[x] = Find(father[x]);}LL kruscal(){ LL ans = 0; int judge = 0; sort(Edge + 1, Edge + tot + 1); for(int i = 1; i <= tot; i++) { int u = Edge[i].v; int v = Edge[i].u; LL w = Edge[i].w; int f1 = Find(u); int f2 = Find(v); if(f1 != f2) { judge++; ans += w; father[f1] = f2; } if(judge == n - 1) break; } return ans;}int main(){ freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ; scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &Point[i].x, &Point[i].y); Point[i].id = i; } init(); getGraph(); printf("%lld\n", kruscal()); return 0;}树状数组:
#include <bits/stdc++.h>using namespace std;typedef long long LL;inline bool scan_d(int &num){ char in;bool IsN=false; in=getchar(); if(in==EOF) return false; while(in!='-'&&(in<'0'||in>'9')) in=getchar(); if(in=='-'){ IsN=true;num=0;} else num=in-'0'; while(in=getchar(),in>='0'&&in<='9'){ num*=10,num+=in-'0'; } if(IsN) num=-num; return true;}const int maxn = 100000 + 10;LL inf = 1e18;int n;int tot;int father[maxn];struct point{ int x, y, id; bool operator <(const point &res) const { if(x == res.x) return y < res.y; else return x < res.x; }} Point[maxn<<4];struct edge{ int u, v; LL w; bool operator <(const edge &res) const { return w < res.w; }} Edge[maxn<<10];struct BITnode{ LL w; int id;}Tree[maxn<<1];LL H[maxn<<1];int num;int lowbit(int x){ return x&(-x);}int Hash(LL key){ return lower_bound(H, H + num, key) - H + 1;}void add_edge(int u, int v, LL w){ Edge[++tot].u = u; Edge[tot].v = v; Edge[tot].w = w;}void Tran(int type){ if(type == 1) { sort(Point + 1, Point + n + 1); return; } else if(type == 2 || type == 4) { for(int i = 1; i <= n; i++) { swap(Point[i].x, Point[i].y); } sort(Point + 1, Point + n + 1); return; } else if(type == 3) { for(int i = 1; i <= n; i++) { Point[i].x = -Point[i].x; } sort(Point + 1, Point + n + 1); return; }}void add(int loc, LL v, int id){ for(int i = loc; i >= 1; i -= lowbit(i)) { if(Tree[i].w > v) { Tree[i].w = v; Tree[i].id = id; } }}int query(int loc){ LL Min = inf; int id = -1; for(int i = loc; i <= num; i += lowbit(i)) { if(Tree[i].w < Min) { Min = Tree[i].w; id = i; } } return id;}void getGraph(){ for(int i = 1; i <= 4; i++) { Tran(i); num = 0; for(int j = n; j >= 1; j--) { Tree[j].id = -1; Tree[j].w = inf; LL key = LL(Point[j].y - Point[j].x); H[num++] = key; } sort(H, H + num); num = unique(H, H + num) - H; for(int j = n; j >= 1; j--) { LL key = LL(Point[j].y - Point[j].x); LL v = LL(Point[j].x + Point[j].y); int loc = Hash(key); int id = query(loc); if(id != -1) { add_edge(Point[j].id, Tree[id].id, Tree[id].w - v); } add(loc, v, Point[j].id); } }}void init(){ tot = 0; for(int i = 1; i <= n; i++) father[i] = i;}int Find(int x){ if(father[x] == x) return x; else return father[x] = Find(father[x]);}LL kruscal(){ LL ans = 0; int judge = 0; sort(Edge + 1, Edge + tot + 1); for(int i = 1; i <= tot; i++) { int u = Edge[i].v; int v = Edge[i].u; LL w = Edge[i].w; int f1 = Find(u); int f2 = Find(v); if(f1 != f2) { judge++; ans += w; father[f1] = f2; } if(judge == n - 1) break; } return ans;}int main(){ // freopen("C:\\Users\\creator\\Desktop\\in1.txt","r",stdin) ; scanf("%d", &n); for(int i = 1; i <= n; i++) { //scanf("%d%d", &Point[i].x, &Point[i].y); scan_d(Point[i].x); scan_d(Point[i].y); Point[i].id = i; } init(); getGraph(); printf("%lld\n", kruscal()); return 0;}
阅读全文
1 0
- kattis Grid MST (最小曼哈顿生成树)
- 曼哈顿最小生成树
- 平面曼哈顿最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- 曼哈顿距离最小生成树
- poj3241 曼哈顿最小生成树
- 二维曼哈顿最小生成树
- 最小生成树 MST
- 最小生成树 MST
- MST-最小生成树
- MST 最小生成树
- 最小生成树(MST)
- MST 最小生成树
- 最小生成树(MST)算法
- 最小生成树(MST)
- 最小生成树(MST)
- MST (最小生成树)
- 二、lintcode刷题记录--二叉树的路径和
- Android异常--java.io.FileNotFoundException下载文件时异常
- mysql 优化
- 使用mysql 自带的语句构建批量更新
- Delphi XE MD5加密
- kattis Grid MST (最小曼哈顿生成树)
- 20171020测试
- 单点登录之,客户端
- PHP生成一个简单的验证码图片
- Java NIO核心组成部分
- Hadoop中的Python框架的使用指南
- 内存泄露检测方法
- 1109. Group Photo (25)
- 使用 Skeleton Screen 提升用户感知体验