zoukankan      html  css  js  c++  java
  • 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
    ", 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 }
  • 相关阅读:
    iOS UITextField 设置内边距
    在网页中嵌入任意字体的解决方案
    基数等比,确定进制
    改善CSS编码的5个在线幻灯片教程
    head区的代码详解
    一个简单的、循序渐进的CSS幻灯片教程
    功能强大易用的Web视频播放器——Flowplayer(使用方法及演示)
    CSS:区分IE版本的三个方法
    CSS书写标准及最佳实践
    Sliding Photograph Galleries
  • 原文地址:https://www.cnblogs.com/titicia/p/4425384.html
Copyright © 2011-2022 走看看