Edward has 2n points on the plane conveniently labeled with 1,2,…,2n. Each point is connected exactly with another point by a segment.
Edward finds that some segments intersecting with some others. So he wants to eliminate those intersections with the following operation: choose two points i and j (1 ≤ i, j ≤ 2n) and swap their coordinates.
![swap point 2 and 3](http://acm.zju.edu.cn/onlinejudge/showImage.do?name=swap_points.png)
For example, Edward has 4 points (0, 0), (0, 1), (1, 1), (1, 0). Point 1 is connected with point 3 and point 2 is connected with 4. Edward can choose to swap the coordinates of point 2 and point 3.
Edward wants to know whether it is possible to use at most n + 10 operations to achieve his goal.
No two points coincide and no three points are on the same line.
Input
There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:
The first line contains an integer n (1 ≤ n ≤ 100000).
Each of the following 2n lines contains 2 integers xi, yi which denotes the point (xi, yi). (|xi|, |yi| ≤ 109).
Each of the following n lines contains 2 integers ai, bi (1 ≤ ai, bi ≤ 2n, ai ≠ bi), which means point ai and point bi are connected by a segment.
The sum of values n for all the test cases does not exceed 300000.
Output
For each test case, print a line containing an integer m, indicating the number of operations needed. You must assure that m is no larger than n + 10. If you cannot find such a solution, just output "-1" and ignore the following output.
In the next m lines, each contains two integers i and j (1 ≤ i, j ≤ 2n), indicating an operation, separated by one space.
If there are multiple solutions, any of them is accepted.
Sample Input
1 2 0 0 0 1 1 1 1 0 1 3 2 4
Sample Output
#include<iostream> #include<algorithm> #include<stdio.h> using namespace std; typedef long long LL; #define maxn (100005*2) struct Node { int x,y; int cnt; Node(){cnt=x=y=0;} }; bool cmp(const Node& n1,const Node &n2) { if(n1.x==n2.x) return n1.y<n2.y; return n1.x<n2.x; }//把点分类,按横坐标排序 Node seq[maxn]; int conn[maxn],pos[maxn];//conn数组存储边的映射关系,pos数组存储排序后下标的改变关系 int ans1[maxn],ans2[maxn],cnt;//存储最后的结果 int n; int main() { int x,y; int t;cin>>t; while(t--) { cnt=0; cin>>n; for(int i=1;i<=2*n;i++) { scanf("%d %d",&seq[i].x,&seq[i].y); seq[i].cnt=i;//給每个点按序分配个下标 } for(int i=0;i<n;i++) { int u,v; cin>>u>>v; conn[u]=v; conn[v]=u;//存储边的关系 } sort(seq+1,seq+2*n+1,cmp); for(int i=1;i<=2*n;i++) pos[seq[i].cnt]=i;//映射很重要,方便后期的处理时找点,因为conn数组存储的是原来的下标关系 for(int i=1;i<=2*n;i+=2) { int u=seq[i].cnt,v=seq[i+1].cnt; if(conn[u]==v) continue; int tmp=conn[u]; ans1[cnt]=tmp; ans2[cnt++]=v; seq[pos[tmp]].cnt=v;//技巧:只需要改变一个就可以了,因为前面两个不会再被访问了 swap(pos[tmp],pos[v]);//更新pos映射 } printf("%d\n",cnt); //cout<<cnt<<endl; for(int i=0;i<cnt;i++) printf("%d %d\n",ans1[i],ans2[i]); } return 0;
}
把点集按横坐标排序,分析出相邻两个点如果有线段关系则直接跳过,
若没有线段关系则贪心的交换操作(别忘了更新映射数组。。有点麻烦)