ZOJ-3862-Intersection【贪心】

来源:互联网 发布:计算机语言翻译软件 编辑:程序博客网 时间:2024/05/17 03:03

3862-Intersection


        Time Limit: 3 Seconds      Memory Limit: 131072 KB 

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
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

1
2 3

题目链接:ZOJ-3862

题目大意:给出2 * n个点的位置,以及n条线段,每个点属于且仅属于一条线段。问,如何交换点,使得每条线段互不相交。交换m次需<n+10

题目思路:贪心。首先将这个点,由x小到大排序,分别记录位置编号为1,2,3…. 2 * n。 我们可以将1和2相连,因为这两个点在最左边,所以不会和其他点纠缠。同理3和4连….这样的操作最多n次。所以一定能存在合理的答案。

注意:两个点交换位置时:1. 记录答案 ;2.交换两个点的no值以及vis值

以下是代码:

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <algorithm>#include <map>using namespace std;struct node{    int x,y,no;}p[200005]; //用于记录各个点的位置以及编号map <int,int> mp;  //mp[i] = j 表示  i点与j点相连bool cmp1(node a,node b)  //以x小的先排{    if (a.x != b.x) return a.x < b.x;    else return a.y < b.y;}int last[200005];  //记录交换的答案int vis[200005];  //vis[i] = j 表示 编号为i的点 在排好序的序列中排第几位int main(){    int t;    cin >> t;    while(t--)    {        memset(last,0,sizeof(last));        memset(vis,0,sizeof(vis));        mp.clear();        int n;        scanf("%d",&n);        for (int i = 0; i < 2 * n; i++)        {            scanf("%d%d",&p[i].x,&p[i].y);            p[i].no = i + 1;        }        for (int i = 0; i < n; i++)        {            int a,b;            scanf("%d %d",&a,&b);            mp[a] = b;            mp[b] = a;        }        int k = 0;        int ans = 0;        sort(p,p + n*2,cmp1);        for (int i = 0; i < n * 2; i++)        {            vis[p[i].no] = i;        }        for (int i = 0; i < n * 2; i += 2)        {            int u = p[i].no;            int v = p[i + 1].no;            if (mp[u] == v) continue;            else            {                int u_con = mp[u];                last[k++] = v;                last[k++] = u_con;                swap(p[i + 1].no,p[vis[u_con]].no);                ans++;                swap(vis[v],vis[u_con]);            }        }        printf("%d\n",ans);        for (int i = 0; i < k; i += 2)        {            printf("%d %d\n",last[i],last[i + 1]);        }    }    return 0;}
0 0