思路:

已知:

要生成曼哈顿距离最小生成树,一个点最多和四周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 }
View Code