链接:http://arc076.contest.atcoder.jp/tasks/arc076_b
题目大意:给定平面上n个点,任意两点距离定义为 min(|a−c|,|b−d|), 求最小生成树。
分析:可以用类似曼哈顿距离最小生成树的方法,如在y轴顺时针偏45°的区域,取x最小的点,其它区域类似。这么做有点复杂。。区域内的最小点不好求。。
考虑x坐标,每个点只可能和x值相邻的点连,因此可以分别对x y排序,边只取相邻的点,然后再求一下最小生成树。复杂度为O(nlogn)。
1 #include<iostream> 2 #include<algorithm> 3 #include<vector> 4 using namespace std; 5 struct Pair{ 6 int x,y; 7 }p[100005]; 8 struct edge{ 9 int s,t,cost; 10 }e[2][100005]; 11 int s[100005],t[100005],fa[100005]; 12 int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);} 13 bool Cmpx(int a,int b){ 14 return p[a].x<p[b].x; 15 } 16 bool Cmpy(int a,int b){ 17 return p[a].y<p[b].y; 18 } 19 bool Cmpe(edge a,edge b){ 20 return a.cost<b.cost; 21 } 22 int main(){ 23 int n; 24 cin>>n; 25 for(int i=0;i<n;i++){ 26 cin>>p[i].x>>p[i].y; 27 fa[i]=i; 28 s[i]=i;t[i]=i; 29 } 30 sort(s,s+n,Cmpx); 31 sort(t,t+n,Cmpy); 32 for(int i=0;i<n-1;i++){ 33 e[0][i].s=s[i+1]; 34 e[0][i].t=s[i]; 35 e[0][i].cost=p[s[i+1]].x-p[s[i]].x; 36 } 37 for(int i=0;i<n-1;i++){ 38 e[1][i].s=t[i+1]; 39 e[1][i].t=t[i]; 40 e[1][i].cost=p[t[i+1]].y-p[t[i]].y; 41 } 42 sort(e[0],e[0]+n-1,Cmpe); 43 sort(e[1],e[1]+n-1,Cmpe); 44 int i=0,j=0,count=0; 45 long long cost=0; 46 while(count<n-1){ 47 if(i<=n-1&&e[0][i].cost<=e[1][j].cost){ 48 int x=Find(e[0][i].s),y=Find(e[0][i].t); 49 fa[x]=y; 50 cost+=e[0][i].cost; 51 }else{ 52 int x=Find(e[1][j].s),y=Find(e[1][j].t); 53 fa[x]=y; 54 cost+=e[1][j].cost; 55 } 56 count++; 57 while(i<n-1&&Find(e[0][i].s)==Find(e[0][i].t))i++; 58 while(j<n-1&&Find(e[1][j].s)==Find(e[1][j].t))j++; 59 } 60 cout<<cost<<endl; 61 return 0; 62 }