LA 3662 Another Minimum Spanning Tree (曼哈顿距离最小生成树 模板)
题目大意:
曼哈顿最小距离生成树
算法讨论:
同上。
这回的模板真的准了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <cstdio> 6 using namespace std; 7 const int N = 100000 + 5; 8 const int M = N * 8; 9 typedef long long ll; 10 const ll oo = 100000000000000LL; 11 12 int n, etot; 13 ll W = 0, c[N]; 14 int fa[N], id[N]; 15 int A[N], B[N]; 16 17 struct Point{ 18 int x, y, id; 19 bool operator < (const Point &a)const { 20 if(a.x == x) return y < a.y; 21 return x < a.x; 22 } 23 }p[N]; 24 25 struct Edge{ 26 int from, to; 27 ll dis; 28 bool operator < (const Edge &a)const { 29 return dis < a.dis; 30 } 31 }e[M]; 32 33 int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);} 34 void update(int x, ll val, int pos){ 35 for(int i = x; i > 0; i -= (i&(-i))){ 36 if(val < c[i]){ 37 c[i] = val; 38 id[i] = pos; 39 } 40 } 41 } 42 int query(int pos, int up){ 43 int res = -1; 44 ll val = oo; 45 for(int i = pos; i <= up; i += (i&(-i))){ 46 if(c[i] < val){ 47 val = c[i]; 48 res = id[i]; 49 } 50 } 51 return res; 52 } 53 void MST(){ 54 int up; 55 for(int dir = 1; dir <= 4; ++ dir){ 56 if(dir % 2 == 0) 57 for(int i = 1; i <= n; ++ i) 58 swap(p[i].x, p[i].y); 59 else if(dir == 3) 60 for(int i = 1; i <= n; ++ i) 61 p[i].x = -p[i].x; 62 sort(p + 1, p + n + 1); 63 for(int i = 1; i <= n; ++ i) A[i] = B[i] = (int) p[i].y - p[i].x; 64 sort(B + 1, B + n + 1); 65 up = unique(B + 1, B + n + 1) - B - 1; 66 67 for(int i = 1; i <= up; ++ i){ 68 c[i] = oo; id[i] = -1; 69 } 70 71 for(int i = n; i >= 1; -- i){ 72 A[i] = lower_bound(B + 1, B + up + 1, A[i]) - B; 73 int np = query(A[i], up); 74 if(np != -1){ 75 ++ etot; 76 e[etot].from = p[i].id; 77 e[etot].to = p[np].id; 78 e[etot].dis = abs(p[i].x - p[np].x) + abs(p[i].y - p[np].y); 79 } 80 update(A[i], p[i].x + p[i].y, i); 81 } 82 } 83 84 int have = 0; 85 sort(e + 1, e + etot + 1); 86 for(int i = 1; i <= n; ++ i) fa[i] = i; 87 for(int i = 1; i <= etot; ++ i){ 88 int fx = find(e[i].from), fy = find(e[i].to); 89 if(fx != fy){ 90 fa[fx] = fy; 91 ++ have; 92 W += e[i].dis; 93 if(have == n-1) break; 94 } 95 } 96 } 97 98 int main(){ 99 int cnt = 0; 100 while(scanf("%d", &n) && n){ 101 ++ cnt; etot = 0; 102 for(int i = 1; i <= n; ++ i){ 103 scanf("%d%d", &p[i].x, &p[i].y); 104 p[i].id = i; 105 } 106 W = 0; 107 MST(); 108 printf("Case %d: Total Weight = %lld\n", cnt, W); 109 } 110 return 0; 111 }