题目链接: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 ", ans.size()); 72 for(int i = 0; i < ans.size(); i++){ 73 printf("%d %d ", ans[i].a, ans[i].b); 74 } 75 } 76 77 return 0; 78 }