zoj 3862 Intersection

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3862

题意:给你2*n个点,然后是n组数组 a b 表示点a和点b是用火柴连起来的。

问你有没有可能每次交换2个点,最后所有火柴都不相交。交换的次数在n+10次以内。如果可以输出交换的顺序,如果不行输出-1。

思路:可以想到把点按照x从小到大排,如果x相同按照y从小到大排。按照这样的顺序,从1开始,连接点i和点i+1.....这样最后整个图肯定是没有交点的。

那么可以这样考虑:排列后,假如一开始发现点i就和点i+1相连,那么不用做任何操作。

如果发现点i连接的不是点i+1。那么交换点i的连接点和点i+1。即交换p[i].to 和 p[i+1]。

但是其实并不用交换点,改变相关点的连接方式就行了 即改变p[x].to就可以了。这样操作一次之后,点i一定和点i+1相连。所以最多只需要n次。

需要注意的地方就是,由于是直接改变点的连接而不是真正交换点。还需要保存一下这个点现在其实代表的是哪个点

因为如图

 那应该一开始交换点3和点2。但是实际上我只改变了指向,就是把p[1].to = 2, p[2].to = 1, p[3].to = 4, p[4].to = 3。

这图只有4个点如果点比较多。肯定之后点3需要再做操作。那么我对点3操作,实际上是对原来的点2,所以输出应该是2。所以多加了个now变量来保存。。

还是因为写的方式不好,,写的有点太麻烦了。。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <string>
 5 #include <vector>
 6 #include <iomanip>
 7 #include <algorithm>
 8 using namespace std;
 9 class Point{
10     public:
11         int x, y, pre, to, now; 
12         Point(){}
13         Point(const Point &a){
14             x = a.x; y = a.y; pre = a.pre; to = a.to; now = a.now;
15         }
16 }p[100005*2];
17 class Pair{
18     public: int a, b;
19     Pair(int aa, int bb){
20         a = aa; b = bb;
21     }
22 };
23 vector <Pair> ans;
24 int pair[100005*2];
25 int mark[100005*2], mark2[100005*2];
26 bool cmp(Point p1, Point p2){
27     if(p1.x == p2.x) return p1.y < p2.y;
28     else return p1.x < p2.x;
29 }
30 int T, n;
31 int main(){
32     scanf("%d", &T);
33     while(T--){
34         scanf("%d", &n);
35         ans.clear();
36         for(int i = 1; i <= 2*n; i++){
37             scanf("%d%d", &p[i].x, &p[i].y);
38             p[i].pre = i;
39             p[i].now = i;
40         }
41         for(int i = 1; i <= n; i++){
42             int a, b;
43             scanf("%d%d", &a, &b);
44             p[a].to = b; p[b].to = a;
45         }
46         sort(p+1, p+1+2*n, cmp); //排序。
47         for(int i = 1; i <= 2*n; i++){
48             mark[p[i].pre] = i; //mark表示原来的几现在对应的是几。 
49         }
50         for(int i = 1; i <= 2*n; i++){
51             mark2[mark[i]] = i;
52         }
53         //mark2储存了排序后的对应的排序前的序号。
54         //mark储存的是排序前对应的排序后的序号, 
55         for(int i = 1; i <= 2*n; i += 2){
56             if(p[i].to != mark2[i+1]){ 
57                 ans.push_back(Pair(p[mark[p[i].to]].now, p[i+1].now));
58                 
59                 int tempnow = p[mark[p[i].to]].now;
60                 p[mark[p[i].to]].now = p[i+1].now;
61                 p[i+1].now = tempnow;
62                 
63                 int temp1 = p[i].to; int temp2 = p[i+1].to;
64                 p[i].to = mark2[i+1]; 
65                 p[i+1].to = mark2[i];
66                 
67                 p[mark[temp1]].to = temp2;
68                 p[mark[temp2]].to = temp1;
69             }
70         } 
71         printf("%d\n", ans.size());
72         for(int i = 0; i < ans.size(); i++){
73             printf("%d %d\n", ans[i].a, ans[i].b);
74         }
75     }
76     
77     return 0;
78 }

 

posted @ 2015-04-14 16:54  下周LGD该赢了吧  阅读(250)  评论(0编辑  收藏  举报