https://codeforces.com/contest/958/problem/E3
当没有三点共线时,任意一个这样的点集都是保证可以找到答案的,(考虑任意一种有相交的连线方案,一定可以将其中两条相交的连线改成不相交的,并使得连线的总长度变小;显然连线的总长度最小的方案一定存在,则这种方案一定没有连线相交)
因此可以有一个分治做法:先在当前点集中找出最左、最下的点,找出一个点与其配对,使得以这两点间连线所在的直线划分开点集后,两边各自都满足白点数等于黑点数;显然一定能找到这个与其配对的点
找的方法就是其他点以选出这个点为中心做极角排序,然后双指针
复杂度n^2*log
本来以为分治时可以随便找出一个点,但事实上这样不对的,举个例子:
(以A2为选出点,则找不到配对点)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<cmath> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 namespace X 15 { 16 struct Point 17 { 18 int x,y; 19 Point(int x=0,int y=0):x(x),y(y){} 20 }; 21 typedef Point Vec; 22 Vec operator+(const Vec& a,const Vec& b) 23 { 24 return Vec(a.x+b.x,a.y+b.y); 25 } 26 Vec operator-(const Vec& a,const Vec& b) 27 { 28 return Vec(a.x-b.x,a.y-b.y); 29 } 30 int dcmp(int x) 31 //正为1,负为-1,0为0 32 { 33 if(x==0) return 0; 34 return x<0?-1:1; 35 } 36 bool operator==(const Vec& a,const Vec& b) 37 //判向量相等 38 { 39 return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; 40 } 41 double cross(const Vec& a,const Vec& b) 42 //叉积 43 { 44 return a.x*b.y-a.y*b.x; 45 } 46 }; 47 using namespace X; 48 Point p[20100]; 49 int an[10100]; 50 int d[20100],tmp[20100]; 51 int n; 52 double ang[20100]; 53 bool vis[20100]; 54 bool c1(int a,int b) 55 { 56 return ang[a]<ang[b]; 57 } 58 bool c2(int a,int b) 59 { 60 return p[a].x<p[b].x||(p[a].x==p[b].x&&p[a].y<p[b].y); 61 } 62 void solve(int l,int r) 63 { 64 if(r<l) return; 65 swap(*min_element(d+l,d+r+1,c2),d[l]); 66 int i; 67 for(i=l+1;i<=r;i++) 68 ang[d[i]]=atan2(p[d[i]].y-p[d[l]].y,p[d[i]].x-p[d[l]].x); 69 sort(d+l+1,d+r+1,c1); 70 int len=r-l,a[]={0,0},nl,nr; 71 for(nl=l+1,nr=l;nl<=r;nl++)//包含(nl,nr]的点,nl自身与l相连 72 { 73 while(nr<nl||(nr-nl+1<len&&cross(p[d[(nr-l)%len+l+1]]-p[d[l]],p[d[nl]]-p[d[l]])<0)) 74 { 75 ++nr; 76 a[d[(nr-l-1)%len+l+1]<=n]++; 77 } 78 a[d[nl]<=n]--; 79 if(int(d[nl]<=n)+(d[l]<=n)==1&&a[0]==a[1]) break; 80 } 81 if(d[l]<=n) an[d[l]]=d[nl]; 82 else an[d[nl]]=d[l]; 83 for(i=l+1;i<=r;i++) 84 vis[i]=0; 85 vis[nl]=1; 86 tmp[0]=0; 87 for(i=nl+1;i<=nr;i++) 88 { 89 vis[(i-l-1)%len+l+1]=1; 90 tmp[++tmp[0]]=d[(i-l-1)%len+l+1]; 91 } 92 int t1=l; 93 for(i=l+1;i<=r;i++) 94 if(!vis[i]) 95 { 96 d[++t1]=d[i]; 97 } 98 int t2=t1; 99 for(i=1;i<=tmp[0];i++) 100 d[++t2]=tmp[i]; 101 solve(l+1,t1);solve(t1+1,t2); 102 } 103 int main() 104 { 105 int i; 106 while(scanf("%d",&n)==1) 107 { 108 for(i=1;i<=2*n;i++) scanf("%d%d",&p[i].x,&p[i].y); 109 for(i=1;i<=2*n;i++) d[i]=i; 110 solve(1,2*n); 111 for(i=1;i<=n;i++) printf("%d ",an[i]-n); 112 } 113 return 0; 114 }