zoukankan      html  css  js  c++  java
  • ACM1558两线段相交判断和并查集

    Segment set

    Problem Description
    A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set.

     
    Input
    In the first line there is an integer t - the number of test case. For each test case in first line there is an integer n (n<=1000) - the number of commands. 

    There are two different commands described in different format shown below:

    P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
    Q k - query the size of the segment set which contains the k-th segment.

    k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.
     
    Output
    For each Q-command, output the answer. There is a blank line between test cases.
     
    Sample Input
    1
    10
    P 1.00 1.00 4.00 2.00
    P 1.00 -2.00 8.00 4.00
    Q 1 P 2.00 3.00 3.00 1.00
    Q 1
    Q 3
    P 1.00 4.00 8.00 2.00
    Q 2
    P 3.00 3.00 6.00 -2.00
    Q 5
     
    Sample Output
    1
    2
    2
    2
    5
    题意是要求输入一些线段,判断这些线段连接成几个集合,然后求包含某条线段的集合中的元素个数;

     本题主要难关是判断量条线段是否相交,在我这篇文章里有详细介绍判断两条线段相交的方法。http://www.cnblogs.com/sytu/articles/3876585.html;

    Notice:二维向量的叉乘公式是 axb=(x1,y1)x(x2,y2)=x1*y2-y1*x2;

    下面为AC代码:

      1 #include<iostream>
      2 using namespace std;
      3 #define MIN(x,y) (x < y ? x : y)
      4 #define MAX(x,y) (x > y ? x : y)
      5 typedef struct 
      6 {
      7     double x,y;
      8 } Point;
      9 struct LINE
     10 {
     11     double x1,x2,y1,y2;
     12     int flag;    
     13 };
     14 LINE *line;
     15 int lineintersect(int a,int b)
     16 {
     17     Point p1,p2,p3,p4;
     18     p1.x=line[a].x1;p1.y=line[a].y1;
     19     p2.x=line[a].x2;p2.y=line[a].y2;
     20     p3.x=line[b].x1;p3.y=line[b].y1;
     21     p4.x=line[b].x2;p4.y=line[b].y2;
     22     
     23     Point tp1,tp2,tp3,tp4,tp5,tp6;
     24     if ((p1.x==p3.x&&p1.y==p3.y)||(p1.x==p4.x&&p1.y==p4.y)||(p2.x==p3.x&&p2.y==p3.y)||(p2.x==p4.x&&p2.y==p4.y))
     25         return 1;
     26 //快速排斥试验
     27 if(MAX(p1.x,p2.x)<MIN(p3.x,p4.x)||MAX(p3.x,p4.x)<MIN(p1.x,p2.x)||MAX(p1.y,p2.y)<MIN(p3.y,p4.y)||MAX(p3.y,p4.y)<MIN(p1.y,p2.y))
     28             return 0;
     29 //跨立试验
     30     tp1.x=p1.x-p3.x;
     31     tp1.y=p1.y-p3.y;
     32     tp2.x=p4.x-p3.x;
     33     tp2.y=p4.y-p3.y;
     34     tp3.x=p2.x-p3.x;
     35     tp3.y=p2.y-p3.y;//从这到上面是一组的向量
     36     tp4.x=p2.x-p4.x;//下面是一组的向量
     37     tp4.y=p2.y-p4.y;
     38     tp5.x=p2.x-p3.x;
     39     tp5.y=p2.y-p3.y;
     40     tp6.x=p2.x-p1.x;
     41     tp6.y=p2.y-p1.y;
     42     if ((tp1.x*tp2.y-tp1.y*tp2.x)*(tp2.x*tp3.y-tp2.y*tp3.x)>=0) //此处用到了叉乘公式
     43     {
     44         if((tp4.x*tp6.y-tp4.y*tp6.x)*(tp6.x*tp5.y-tp6.y*tp5.x)>=0)
     45             return 1;  
     46     }
     47 return 0;
     48 }
     49 int find(int x)
     50 {
     51     if(0>line[x].flag)return x;
     52     return line[x].flag=find(line[x].flag);
     53 }
     54 void Union(int a,int b)
     55 {
     56     int fa=find(a);
     57     int fb=find(b);
     58     if(fa==fb)return;
     59     int n1=line[fa].flag;
     60     int n2=line[fb].flag;
     61     if(n1>n2)
     62     {
     63         line[fa].flag=fb;
     64         line[fb].flag+=n1;
     65     }
     66     else 
     67     {
     68         line[fb].flag=fa;
     69         line[fa].flag+=n2;
     70     }
     71 }
     72 void throwinto(int n)
     73 {
     74     if(n>1)
     75     {
     76         for(int i=1;i<n;i++)
     77         {
     78             if(lineintersect(i,n))
     79             Union(i,n);
     80         }
     81     }
     82 }
     83 int main()
     84 {
     85     int t;
     86     cin>>t;
     87     int n,q;
     88     int cn=t;
     89     while(t--)
     90     {
     91         
     92         int cnt=1;
     93         cin>>n;
     94         line=new LINE[n+1];
     95         for(int i=0;i<=n;i++)
     96         {
     97             line[i].flag=-1;
     98         }
     99         for(int i=1;i<=n;i++)
    100         {
    101             char sj;
    102             cin>>sj;
    103             if(sj=='P')
    104             {
    105                 cin>>line[cnt].x1>>line[cnt].y1>>line[cnt].x2>>line[cnt].y2;
    106                 throwinto(cnt);
    107                 cnt++;
    108             }
    109             else if(sj=='Q')
    110             {
    111                 cin>>q;
    112                 int re=find(q);
    113                 cout<<-line[re].flag<<endl;
    114             }
    115         }
    116         if(t>0)cout<<endl;//注意格式问题,容易出错
    117     }
    118     return 0;
    119 }
    What I don't dare to say is I can't!
  • 相关阅读:
    IE8下提示'console'未定义错误
    左右添加和删除
    箭头函数
    事件冒泡
    选中状态改变,并且实现左边选中便便添加
    appcan里面模板的使用
    白面机器学习笔记(一)
    常见的模型加速方法
    相机的参数
    深度学习和机器学习的区别
  • 原文地址:https://www.cnblogs.com/sytu/p/3876653.html
Copyright © 2011-2022 走看看