ZOJ3862:Intersection


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 ≤ ij ≤ 2n) and swap their coordinates.

swap point 2 and 3

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 xiyi which denotes the point (xiyi). (|xi|, |yi| ≤ 109).

Each of the following n lines contains 2 integers aibi (1 ≤ aibi ≤ 2nai ≠ 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 ≤ ij ≤ 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

1
2 3


2n个点,然后按顺序编号;然后输入n条线,表示哪两个点相互连接,当然这些在坐标上的线是有交集的,题目要求要做到所有的线都不相交.求至少需要更改多少个坐标点,输出需要变更的点的原序号;
就是先按顺序从左下角至右上角排序(当然其他的排序方法也可以),然后一号二号相连.就可以保证不会和其他的线相交,之后的同理;


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
struct node{
    int a;
    int b;
    int id;
};
int cmp(node x,node y){
    if(x.a==y.a)
        return x.b<y.b;
    return x.a<y.a;
}
node m[200008];
node ans[200008];
int vis[200008];
int rk[200008];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        memset(vis,0,sizeof(vis));
        memset(rk,0,sizeof(rk));
        memset(m,0,sizeof(m));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=2*n;i++){
            scanf("%d%d",&m[i].a,&m[i].b);
            m[i].id=i;
        }
        int p,q;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&p,&q);
            vis[p]=q;
            vis[q]=p;
        }//输入对应相连线的点,并配对.
        sort(m+1, m+n*2+1, cmp); //排序,从左下角的点开始往右上角排序
        for (int i=1; i<=2*n; i++)
            rk[m[i].id] = i;//给原来的顺序再按照现在的顺序标上号,下标为原来的顺序,数组内容为现在的顺序.
        int cnt=0;
        for(int i=1;i<=2*n;i+=2){
            int a=m[i].id,b=m[i+1].id;
            if(vis[a]!=b){//如果不是相连的点.
                cnt++;//交换的点数+1
                ans[cnt].a=b;
                ans[cnt].b=vis[a];//记录交换点的原来顺序
                swap(m[i+1].id,m[rk[vis[a]]].id);//交换现在排好序以后的点的坐标
                swap(rk[b],rk[vis[a]]);//变动现在的点的相应顺序
            }
        }
        printf("%d\n",cnt);
        for (int i=1; i<=cnt; i++)
            printf("%d %d\n",ans[i].a,ans[i].b);
    }
    return 0;
}



比较坑的是我用cin,cout就超时了,最后改成scanf和printf就过了.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值