思路:
已知:
要生成曼哈顿距离最小生成树,一个点最多和四周8个点连线,那8个点分别是将那个点四周360度平分成8个区间,每个区间里面和那个点曼哈顿距离最小的点,所以如果有n个点,那么最多有4n条边,然后就可以用kruskal算法去做。
1 #include <iostream> //poj3241 曼哈顿距离最小生成树第k大的边 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <climits> 6 #define mid ((l+r)>>1) 7 using namespace std; 8 9 int ent; 10 11 int temp1,temp2,temp3; 12 13 int fa[11000]; 14 15 class Point 16 { 17 public: 18 int x,y,id; 19 } point[11000]; 20 21 class Tree 22 { 23 public: 24 int index,current; 25 } tree[2200<<2]; 26 27 class Edge 28 { 29 public: 30 int s,t,dis; 31 } edge[44000]; 32 33 bool cmp(Point a,Point b) 34 { 35 if(a.x==b.x) 36 return a.y<b.y; 37 return a.x<b.x; 38 } 39 40 bool cmp2(Edge a,Edge b) 41 { 42 return a.dis<b.dis; 43 } 44 45 int get_ans(Point a) 46 { 47 return a.y-a.x+1100; 48 } 49 50 int get_dis(int a,int b) 51 { 52 return point[b].x+point[b].y-point[a].x-point[a].y; 53 } 54 55 void build(int l,int r,int n) 56 { 57 tree[n].index=INT_MAX; 58 if(l==r) 59 { 60 tree[n].current=l; 61 return; 62 } 63 build(l,mid,n<<1); 64 build(mid+1,r,n<<1|1); 65 } 66 67 void update(int l,int r,int n,int current,int aim) 68 { 69 int ans=point[aim].x+point[aim].y; 70 if(ans<tree[n].index) 71 tree[n].index=ans; 72 if(l==r) 73 { 74 if(ans==tree[n].index) 75 tree[n].current=aim; 76 return; 77 } 78 if(mid<current) 79 update(mid+1,r,n<<1|1,current,aim); 80 else update(l,mid,n<<1,current,aim); 81 } 82 83 void search(int l,int r,int n,int current,int aim) 84 { 85 if(l==r) 86 { 87 if(tree[n].index<temp1) 88 { 89 temp1=tree[n].index; 90 temp2=tree[n].current; 91 } 92 return; 93 } 94 if(mid<current) 95 search(mid+1,r,n<<1|1,current,aim); 96 else if(l>=current) 97 { 98 if(tree[n<<1].index<tree[n<<1|1].index) 99 search(l,mid,n<<1,current,aim); 100 else search(mid+1,r,n<<1|1,current,aim); 101 } 102 else 103 { 104 if(tree[n<<1].index>=tree[n<<1|1].index) 105 search(mid+1,r,n<<1|1,current,aim); 106 else 107 { 108 search(l,mid,n<<1,current,aim); 109 search(mid+1,r,n<<1|1,current,aim); 110 } 111 } 112 } 113 114 int find(int x) 115 { 116 int temp=x; 117 while(x!=fa[x]) 118 x=fa[x]; 119 while(temp!=fa[temp]) 120 { 121 temp=fa[temp]; 122 fa[temp]=x; 123 } 124 return x; 125 } 126 127 int pos[2200]; 128 bool sign[2200]; 129 int ans[2200]; 130 131 int main() 132 { 133 int n,k; 134 while(cin>>n>>k) 135 { 136 int m=0; 137 ent=0; 138 memset(sign,false,sizeof(sign)); 139 for(int i=0; i<n; i++) 140 { 141 scanf("%d%d",&point[i].x,&point[i].y); 142 point[i].id=i; 143 } 144 for(int tot=0; tot<4; tot++) 145 { 146 if(tot==2) 147 { 148 for(int i=0; i<n; i++) 149 point[i].y=-point[i].y; 150 } 151 if(tot==1||tot==3) 152 { 153 for(int i=0; i<n; i++) 154 { 155 point[i].x=point[i].x+point[i].y; 156 point[i].y=point[i].x-point[i].y; 157 point[i].x=point[i].x-point[i].y; 158 } 159 } 160 for(int i=0; i<n; i++) 161 { 162 int temp=get_ans(point[i]); 163 if(!sign[temp]) 164 { 165 pos[m++]=temp; 166 sign[temp]=true; 167 } 168 } 169 sort(pos,pos+m); 170 for(int i=0; i<m; i++) 171 { 172 ans[pos[i]]=i; 173 } 174 sort(point,point+n,cmp); 175 build(0,m-1,1); 176 for(int i=n-1; i>0; i--) 177 { 178 update(0,m-1,1,ans[get_ans(point[i])],i); 179 temp1=INT_MAX; 180 search(0,m-1,1,ans[get_ans(point[i-1])],i-1); 181 if(temp1!=INT_MAX) 182 { 183 edge[ent].s=point[i-1].id,edge[ent].t=point[temp2].id; 184 edge[ent++].dis=get_dis(i-1,temp2); 185 } 186 } 187 } 188 sort(edge,edge+ent,cmp2); 189 for(int i=0; i<=n; i++) 190 fa[i]=i; 191 int tot=0; 192 for(int i=0; i<ent; i++) 193 { 194 int x=find(edge[i].s); 195 int y=find(edge[i].t); 196 if(x==y) 197 continue; 198 else 199 { 200 fa[y]=x; 201 tot++; 202 } 203 if(tot==n-k) 204 { 205 cout<<edge[i].dis<<endl; 206 break; 207 } 208 } 209 } 210 return 0; 211 }